summaryrefslogtreecommitdiff
path: root/src/script/common
diff options
context:
space:
mode:
authorShadowNinja <shadowninja@minetest.net>2013-11-05 12:06:15 -0500
committerShadowNinja <shadowninja@minetest.net>2013-11-15 14:13:31 -0500
commit371b39a09a0bf248d674fae718f5ff369e895b66 (patch)
treeda8bb27e27a9c89eac895d211721de11a3781533 /src/script/common
parent3f519eb72922607329e1e6a48768d84d1f443efc (diff)
downloadminetest-371b39a09a0bf248d674fae718f5ff369e895b66.tar.gz
minetest-371b39a09a0bf248d674fae718f5ff369e895b66.tar.bz2
minetest-371b39a09a0bf248d674fae718f5ff369e895b66.zip
Pass a errfunc to lua_pcall to get a traceback
Diffstat (limited to 'src/script/common')
-rw-r--r--src/script/common/c_content.cpp9
-rw-r--r--src/script/common/c_internal.cpp56
-rw-r--r--src/script/common/c_internal.h9
-rw-r--r--src/script/common/c_types.cpp5
4 files changed, 49 insertions, 30 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<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
}
/******************************************************************************/
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:
- // ... <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
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[] =