Pass a errfunc to lua_pcall to get a traceback 995/head
authorShadowNinja <shadowninja@minetest.net>
Tue, 5 Nov 2013 17:06:15 +0000 (12:06 -0500)
committerShadowNinja <shadowninja@minetest.net>
Fri, 15 Nov 2013 19:13:31 +0000 (14:13 -0500)
19 files changed:
src/script/common/c_content.cpp
src/script/common/c_internal.cpp
src/script/common/c_internal.h
src/script/common/c_types.cpp
src/script/cpp_api/s_base.cpp
src/script/cpp_api/s_base.h
src/script/cpp_api/s_entity.cpp
src/script/cpp_api/s_inventory.cpp
src/script/cpp_api/s_item.cpp
src/script/cpp_api/s_mainmenu.cpp
src/script/cpp_api/s_node.cpp
src/script/cpp_api/s_nodemeta.cpp
src/script/cpp_api/s_server.cpp
src/script/lua_api/l_base.h
src/script/lua_api/l_craft.cpp
src/script/lua_api/l_env.cpp
src/script/lua_api/l_noise.cpp
src/script/lua_api/l_rollback.cpp
src/script/lua_api/l_server.cpp

index a035b32a2d644820bdea4ef202ced1d1246d6afb..2ad4c95656d356cfcd90741432a95eefbc44fe9f 100644 (file)
@@ -871,6 +871,8 @@ void read_groups(lua_State *L, int index,
 /******************************************************************************/
 void push_items(lua_State *L, const std::vector<ItemStack> &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<ItemStack> &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
 }
 
 /******************************************************************************/
index 5c16b88d9d281c8518122f8fd05ed736bef9db6d..7415aecb83277d1da868801c054bcce00cb82943 100644 (file)
@@ -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:
-       // ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n>
+       // ... <return value = nil> <error handler> <table> <arg#1> <arg#2> ... <arg#n>
 
-       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
index 9a50b8e960c18db32cd65a97cb9ac02c7f7ef96c..eb6aa06e87e762c408384fcdf5d5c40d800a83a9 100644 (file)
@@ -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_ */
index ac724c42c84d9ce73758c7e5f07ea2e4f2030e39..a6faf98197f17eaafe3a922b9baa6bdb7968a7b7 100644 (file)
@@ -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[] =
index e26d54ba71302a47cd4d3c49ba787c9e41843199..b1272b64e95b895445be17dcc1a8101ab0571313 100644 (file)
@@ -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<<std::endl;
                errorstream<<lua_tostring(L, -1)<<std::endl;
                errorstream<<std::endl;
-               errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl;
+               errorstream<<"======= END OF ERROR FROM LUA ========"<<std::endl;
                lua_pop(L, 1); // Pop error message from stack
                lua_pop(L, 1); // Pop the error handler from stack
                return false;
@@ -159,19 +142,13 @@ void ScriptApiBase::realityCheck()
        if(top >= 30){
                dstream<<"Stack is over 30:"<<std::endl;
                stackDump(dstream);
-               scriptError("Stack is over 30 (reality check)");
+               throw LuaError(m_luastack, "Stack is over 30 (reality check)");
        }
 }
 
-void ScriptApiBase::scriptError(const char *fmt, ...)
+void ScriptApiBase::scriptError()
 {
-       va_list argp;
-       va_start(argp, fmt);
-       char buf[10000];
-       vsnprintf(buf, 10000, fmt, argp);
-       va_end(argp);
-       //errorstream<<"SCRIPT ERROR: "<<buf;
-       throw LuaError(m_luastack, buf);
+       throw LuaError(NULL, lua_tostring(m_luastack, -1));
 }
 
 void ScriptApiBase::stackDump(std::ostream &o)
index 63f7e423fb256e1b953ecdac017119fc8186851d..75552cc34f9bac163ba91fc14110b879834cde39 100644 (file)
@@ -31,6 +31,7 @@ extern "C" {
 #include "jthread/jmutex.h"
 #include "jthread/jmutexautolock.h"
 #include "common/c_types.h"
+#include "common/c_internal.h"
 
 #define SCRIPTAPI_LOCK_DEBUG
 
@@ -65,7 +66,7 @@ protected:
                { return m_luastack; }
 
        void realityCheck();
-       void scriptError(const char *fmt, ...);
+       void scriptError();
        void stackDump(std::ostream &o);
 
        Server* getServer() { return m_server; }
index cefa27cb18eef653ea6662e25f4a494042ada11e..c9d1bd8e0c06857c39277248850c497d8a30c768 100644 (file)
@@ -78,25 +78,29 @@ void ScriptApiEntity::luaentity_Activate(u16 id,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        verbosestream<<"scriptapi_luaentity_activate: id="<<id<<std::endl;
 
        // Get minetest.luaentities[id]
-       luaentity_get(L,id);
+       luaentity_get(L, id);
        int object = lua_gettop(L);
 
        // Get on_activate function
-       lua_pushvalue(L, object);
        lua_getfield(L, -1, "on_activate");
-       if(!lua_isnil(L, -1)){
+       if(!lua_isnil(L, -1)) {
                luaL_checktype(L, -1, LUA_TFUNCTION);
                lua_pushvalue(L, object); // self
                lua_pushlstring(L, staticdata.c_str(), staticdata.size());
                lua_pushinteger(L, dtime_s);
                // Call with 3 arguments, 0 results
-               if(lua_pcall(L, 3, 0, 0))
-                       scriptError("error running function on_activate: %s\n",
-                                       lua_tostring(L, -1));
+               if(lua_pcall(L, 3, 0, errorhandler))
+                       scriptError();
+       } else {
+               lua_pop(L, 1);
        }
+       lua_pop(L, 2); // Pop object and error handler
 }
 
 void ScriptApiEntity::luaentity_Remove(u16 id)
@@ -123,14 +127,16 @@ std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        //infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
 
        // Get minetest.luaentities[id]
-       luaentity_get(L,id);
+       luaentity_get(L, id);
        int object = lua_gettop(L);
 
        // Get get_staticdata function
-       lua_pushvalue(L, object);
        lua_getfield(L, -1, "get_staticdata");
        if(lua_isnil(L, -1))
                return "";
@@ -138,11 +144,12 @@ std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
        luaL_checktype(L, -1, LUA_TFUNCTION);
        lua_pushvalue(L, object); // self
        // Call with 1 arguments, 1 results
-       if(lua_pcall(L, 1, 1, 0))
-               scriptError("error running function get_staticdata: %s\n",
-                               lua_tostring(L, -1));
+       if(lua_pcall(L, 1, 1, errorhandler))
+               scriptError();
+       lua_remove(L, object); // Remove object
+       lua_remove(L, errorhandler); // Remove error handler
 
-       size_t len=0;
+       size_t len = 0;
        const char *s = lua_tolstring(L, -1, &len);
        return std::string(s, len);
 }
@@ -192,10 +199,13 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
 
        // Get minetest.luaentities[id]
-       luaentity_get(L,id);
+       luaentity_get(L, id);
        int object = lua_gettop(L);
        // State: object is at top of stack
        // Get step function
@@ -206,8 +216,10 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
        lua_pushvalue(L, object); // self
        lua_pushnumber(L, dtime); // dtime
        // Call with 2 arguments, 0 results
-       if(lua_pcall(L, 2, 0, 0))
-               scriptError("error running function 'on_step': %s\n", lua_tostring(L, -1));
+       if(lua_pcall(L, 2, 0, errorhandler))
+               scriptError();
+       lua_remove(L, object); // Remove object
+       lua_remove(L, errorhandler); // Remove error handler
 }
 
 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
@@ -218,6 +230,9 @@ void ScriptApiEntity::luaentity_Punch(u16 id,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
 
        // Get minetest.luaentities[id]
@@ -235,8 +250,10 @@ void ScriptApiEntity::luaentity_Punch(u16 id,
        push_tool_capabilities(L, *toolcap);
        push_v3f(L, dir);
        // Call with 5 arguments, 0 results
-       if(lua_pcall(L, 5, 0, 0))
-               scriptError("error running function 'on_punch': %s\n", lua_tostring(L, -1));
+       if(lua_pcall(L, 5, 0, errorhandler))
+               scriptError();
+       lua_remove(L, object); // Remove object
+       lua_remove(L, errorhandler); // Remove error handler
 }
 
 // Calls entity:on_rightclick(ObjectRef clicker)
@@ -245,6 +262,9 @@ void ScriptApiEntity::luaentity_Rightclick(u16 id,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
 
        // Get minetest.luaentities[id]
@@ -259,7 +279,9 @@ void ScriptApiEntity::luaentity_Rightclick(u16 id,
        lua_pushvalue(L, object); // self
        objectrefGetOrCreate(clicker); // Clicker reference
        // Call with 2 arguments, 0 results
-       if(lua_pcall(L, 2, 0, 0))
-               scriptError("error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
+       if(lua_pcall(L, 2, 0, errorhandler))
+               scriptError();
+       lua_remove(L, object); // Remove object
+       lua_remove(L, errorhandler); // Remove error handler
 }
 
index 09f26d80caceb92c6a47eadd7f3a1db64d025d87..4ee6e4be0fd6a5be973a34ede5c16d08ee5c0a25 100644 (file)
@@ -33,6 +33,9 @@ int ScriptApiDetached::detached_inventory_AllowMove(
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getDetachedInventoryCallback(name, "allow_move"))
                return count;
@@ -42,23 +45,19 @@ int ScriptApiDetached::detached_inventory_AllowMove(
        InventoryLocation loc;
        loc.setDetached(name);
        InvRef::create(L, loc);
-       // 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));
+       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();
        if(!lua_isnumber(L, -1))
                throw LuaError(L, "allow_move should return a number");
-       return luaL_checkinteger(L, -1);
+       int ret = luaL_checkinteger(L, -1);
+       lua_pop(L, 2); // Pop integer and error handler
+       return ret;
 }
 
 // Return number of accepted items to be put
@@ -69,28 +68,28 @@ int ScriptApiDetached::detached_inventory_AllowPut(
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getDetachedInventoryCallback(name, "allow_put"))
                return stack.count; // All will be accepted
 
        // Call function(inv, listname, index, stack, player)
-       // inv
        InventoryLocation loc;
        loc.setDetached(name);
-       InvRef::create(L, loc);
-       // 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));
+       InvRef::create(L, loc);              // inv
+       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();
        if(!lua_isnumber(L, -1))
                throw LuaError(L, "allow_put should return a number");
-       return luaL_checkinteger(L, -1);
+       int ret = luaL_checkinteger(L, -1);
+       lua_pop(L, 2); // Pop integer and error handler
+       return ret;
 }
 
 // Return number of accepted items to be taken
@@ -101,28 +100,28 @@ int ScriptApiDetached::detached_inventory_AllowTake(
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getDetachedInventoryCallback(name, "allow_take"))
                return stack.count; // All will be accepted
 
        // Call function(inv, listname, index, stack, player)
-       // inv
        InventoryLocation loc;
        loc.setDetached(name);
-       InvRef::create(L, loc);
-       // 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));
+       InvRef::create(L, loc);              // inv
+       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();
        if(!lua_isnumber(L, -1))
                throw LuaError(L, "allow_take should return a number");
-       return luaL_checkinteger(L, -1);
+       int ret = luaL_checkinteger(L, -1);
+       lua_pop(L, 2); // Pop integer and error handler
+       return ret;
 }
 
 // Report moved items
@@ -134,6 +133,9 @@ void ScriptApiDetached::detached_inventory_OnMove(
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getDetachedInventoryCallback(name, "on_move"))
                return;
@@ -143,20 +145,15 @@ void ScriptApiDetached::detached_inventory_OnMove(
        InventoryLocation loc;
        loc.setDetached(name);
        InvRef::create(L, loc);
-       // 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));
+       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
@@ -167,6 +164,9 @@ void ScriptApiDetached::detached_inventory_OnPut(
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getDetachedInventoryCallback(name, "on_put"))
                return;
@@ -176,16 +176,13 @@ void ScriptApiDetached::detached_inventory_OnPut(
        InventoryLocation loc;
        loc.setDetached(name);
        InvRef::create(L, loc);
-       // 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));
+       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
@@ -196,6 +193,9 @@ void ScriptApiDetached::detached_inventory_OnTake(
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getDetachedInventoryCallback(name, "on_take"))
                return;
@@ -205,16 +205,13 @@ void ScriptApiDetached::detached_inventory_OnTake(
        InventoryLocation loc;
        loc.setDetached(name);
        InvRef::create(L, loc);
-       // 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));
+       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
 }
 
 // Retrieves minetest.detached_inventories[name][callbackname]
index 1d5f218cf1e20c07b84540b1cc6443b5465746cb..49729e57baebf087d17c4b818677e636e20b9461 100644 (file)
@@ -34,6 +34,9 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getItemCallback(item.name.c_str(), "on_drop"))
                return false;
@@ -42,10 +45,11 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item,
        LuaItemStack::create(L, item);
        objectrefGetOrCreate(dropper);
        pushFloatPos(L, pos);
-       if(lua_pcall(L, 3, 1, 0))
-               scriptError("error: %s", lua_tostring(L, -1));
+       if(lua_pcall(L, 3, 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;
 }
 
@@ -54,6 +58,9 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getItemCallback(item.name.c_str(), "on_place"))
                return false;
@@ -62,10 +69,11 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item,
        LuaItemStack::create(L, item);
        objectrefGetOrCreate(placer);
        pushPointedThing(pointed);
-       if(lua_pcall(L, 3, 1, 0))
-               scriptError("error: %s", lua_tostring(L, -1));
+       if(lua_pcall(L, 3, 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;
 }
 
@@ -74,6 +82,9 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Push callback function on stack
        if(!getItemCallback(item.name.c_str(), "on_use"))
                return false;
@@ -82,10 +93,11 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
        LuaItemStack::create(L, item);
        objectrefGetOrCreate(user);
        pushPointedThing(pointed);
-       if(lua_pcall(L, 3, 1, 0))
-               scriptError("error: %s", lua_tostring(L, -1));
+       if(lua_pcall(L, 3, 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;
 }
 
@@ -94,6 +106,9 @@ bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        lua_getglobal(L, "minetest");
        lua_getfield(L, -1, "on_craft");
        LuaItemStack::create(L, item);
@@ -106,10 +121,11 @@ bool ScriptApiItem::item_OnCraft(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;
 }
 
@@ -118,11 +134,14 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        lua_getglobal(L, "minetest");
        lua_getfield(L, -1, "craft_predict");
        LuaItemStack::create(L, item);
        objectrefGetOrCreate(user);
-       
+
        //Push inventory list
        std::vector<ItemStack> items;
        for(u32 i=0; i<old_craft_grid->getSize(); 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 \""<<name<<"\" not defined"<<std::endl;
+               errorstream << "Item \"" << name << "\" not defined" << std::endl;
                lua_pop(L, 1);
 
                // Try minetest.nodedef_default instead
@@ -167,24 +187,16 @@ bool ScriptApiItem::getItemCallback(const char *name, const char *callbackname)
                luaL_checktype(L, -1, LUA_TTABLE);
        }
        lua_getfield(L, -1, callbackname);
-       lua_remove(L, -2);
+       lua_remove(L, -2); // Remove item def
        // Should be a function or nil
-       if(lua_type(L, -1) == LUA_TFUNCTION)
-       {
+       if (lua_type(L, -1) == LUA_TFUNCTION) {
                return true;
+       } else if (!lua_isnil(L, -1)) {
+               errorstream << "Item \"" << name << "\" callback \""
+                       << callbackname << "\" is not a function" << std::endl;
        }
-       else if(lua_isnil(L, -1))
-       {
-               lua_pop(L, 1);
-               return false;
-       }
-       else
-       {
-               errorstream<<"Item \""<<name<<"\" callback \""
-                       <<callbackname<<" is not a function"<<std::endl;
-               lua_pop(L, 1);
-               return false;
-       }
+       lua_pop(L, 1);
+       return false;
 }
 
 void ScriptApiItem::pushPointedThing(const PointedThing& pointed)
index af92c59a92f010d403e1a8f381cf07090d41e7f9..5c54f7368668facb78d029b956996e59ff9354b1 100644 (file)
@@ -37,29 +37,41 @@ void ScriptApiMainMenu::handleMainMenuEvent(std::string text)
 {
        SCRIPTAPI_PRECHECKHEADER
 
+       lua_pushcfunction(L, script_error_handler);
+       int errorhandler = lua_gettop(L);
+
        // Get handler function
        lua_getglobal(L, "engine");
        lua_getfield(L, -1, "event_handler");
-       if(lua_isnil(L, -1))
+       lua_remove(L, -2); // Remove engine
+       if(lua_isnil(L, -1)) {
+               lua_pop(L, 1); // Pop event_handler
                return;
+       }
        luaL_checktype(L, -1, LUA_TFUNCTION);
 
        // Call it
        lua_pushstring(L, text.c_str());
-       if(lua_pcall(L, 1, 0, 0))
-               scriptError("error running function engine.event_handler: %s\n",
-                               lua_tostring(L, -1));
+       if(lua_pcall(L, 1, 0, errorhandler))
+               scriptError();
+       lua_pop(L, 1); // Pop error handler
 }
 
 void ScriptApiMainMenu::handleMainMenuButtons(std::map<std::string, std::string> 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<std::string, std::string>
        }
 
        // 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
 }
index 92fd00a7477f68e5a74390faa3bc5fae90be488f..cd8451cf0431ba5d9e7b2a169c0cd827653ad26a 100644 (file)
@@ -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<std::string, std::string>::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
 }
+
index e87464c612a51d2857bac6e0d4570899bef36e39..1f04383f171f4dc62077062ee28b768402573501 100644 (file)
@@ -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() {
index d41805b7b166b138227433bfb9f8607699f29092..4baf90636bcd9027ef29c67548a81215ebcafa5e 100644 (file)
@@ -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);
 }
 
index 71ebd215c1c15cebba0169c20e48b8b576baa23f..808043bd49c318848799362ee023ac71a460186a 100644 (file)
@@ -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 <lua.h>
index b0a47bfc195bdf3b4b669611e62484cc1afe8ce5..c5732bad2e1b0f2d966eefd4f18d8215205f3680 100644 (file)
@@ -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;
index 436eb014d77f44c20c760c44eee0cd41e34165e6..9bed23d473f1878c14b0993266197ba20757eff4 100644 (file)
@@ -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;
index ecbda9fadd5e39baba12656d2a47af6ae90934c2..4b0c7932ddb31ee83c29c06e94d20453f519c3fc 100644 (file)
@@ -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;
index 6076399aebfa60f93164a8173fed44c4fa42ac36..d5abe176e4e551c6bcf20cc04acb2bfdd10d3fea 100644 (file)
@@ -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
index 8e809c36a32c6891fdc7706a3b85564602854e6b..19e2f1bcbe11f1efbd26ce5a1bba1b1482082201 100644 (file)
@@ -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<std::string> 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;
        }