]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/common/c_internal.cpp
Pass a errfunc to lua_pcall to get a traceback
[dragonfireclient.git] / src / script / common / c_internal.cpp
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