]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script.cpp
Attempt to fix some minor memory leaks
[dragonfireclient.git] / src / script.cpp
index edfc596b8f4a114f045c32565d323695fa9359c5..a159f2288e044ebc5ca387dd491cb0af95c5d395 100644 (file)
@@ -31,87 +31,83 @@ extern "C" {
 #include <lauxlib.h>
 }
 
+LuaError::LuaError(lua_State *L, const std::string &s)
+{
+       m_s = "LuaError: ";
+       m_s += s + "\n";
+       m_s += script_get_backtrace(L);
+}
+
+std::string script_get_backtrace(lua_State *L)
+{
+       std::string s;
+       lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+       if(lua_istable(L, -1)){
+               lua_getfield(L, -1, "traceback");
+               if(lua_isfunction(L, -1)){
+                       lua_call(L, 0, 1);
+                       if(lua_isstring(L, -1)){
+                               s += lua_tostring(L, -1);
+                       }
+                       lua_pop(L, 1);
+               }
+               else{
+                       lua_pop(L, 1);
+               }
+       }
+       lua_pop(L, 1);
+       return s;
+}
+
 void script_error(lua_State *L, const char *fmt, ...)
 {
        va_list argp;
        va_start(argp, fmt);
-       vfprintf(stderr, fmt, argp);
+       char buf[10000];
+       vsnprintf(buf, 10000, fmt, argp);
        va_end(argp);
-       lua_close(L);
-       exit(EXIT_FAILURE);
+       //errorstream<<"SCRIPT ERROR: "<<buf;
+       throw LuaError(L, buf);
 }
 
-void script_call_va(lua_State *L, const char *func, const char *sig, ...)
-{
-       va_list vl;
-       int narg, nres; /* number of arguments and results */
-
-       va_start(vl, sig);
-       lua_getglobal(L, func); /* push function */
-
-       for (narg = 0; *sig; narg++) {
-               /* repeat for each argument */
-               /* check stack space */
-               luaL_checkstack(L, 1, "too many arguments");
-               switch (*sig++) {
-               case 'd': /* double argument */
-                       lua_pushnumber(L, va_arg(vl, double));
-                       break;
-               case 'i': /* int argument */
-                       lua_pushinteger(L, va_arg(vl, int));
-                       break;
-               case 's': /* string argument */
-                       lua_pushstring(L, va_arg(vl, char *));
-                       break;
-               case '>': /* end of arguments */
-                       goto endargs;
-               default:
-                       script_error(L, "invalid option (%c)", *(sig - 1));
-               }
+int luaErrorHandler(lua_State *L) {
+       lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+       if (!lua_istable(L, -1)) {
+               lua_pop(L, 1);
+               return 1;
        }
-endargs:
-
-       nres = strlen(sig); /* number of expected results */
-
-       if (lua_pcall(L, narg, nres, 0) != 0) /* do the call */
-               script_error(L, "error calling '%s': %s", func, lua_tostring(L, -1));
-       
-       nres = -nres; /* stack index of first result */
-       while (*sig) { /* repeat for each result */
-               switch (*sig++) {
-               case 'd': /* double result */
-                       if (!lua_isnumber(L, nres))
-                       script_error(L, "wrong result type");
-                       *va_arg(vl, double *) = lua_tonumber(L, nres);
-                       break;
-               case 'i': /* int result */
-                       if (!lua_isnumber(L, nres))
-                       script_error(L, "wrong result type");
-                       *va_arg(vl, int *) = lua_tointeger(L, nres);
-                       break;
-               case 's': /* string result */
-                       if (!lua_isstring(L, nres))
-                       script_error(L, "wrong result type");
-                       *va_arg(vl, const char **) = lua_tostring(L, nres);
-                       break;
-               default:
-                       script_error(L, "invalid option (%c)", *(sig - 1));
-               }
-               nres++;
+       lua_getfield(L, -1, "traceback");
+       if (!lua_isfunction(L, -1)) {
+               lua_pop(L, 2);
+               return 1;
        }
-
-       va_end(vl);
+       lua_pushvalue(L, 1);
+       lua_pushinteger(L, 2);
+       lua_call(L, 2, 1);
+       return 1;
 }
 
 bool script_load(lua_State *L, const char *path)
 {
-       infostream<<"Loading and running script from "<<path<<std::endl;
-       int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, 0);
+       verbosestream<<"Loading and running script from "<<path<<std::endl;
+
+       lua_pushcfunction(L, luaErrorHandler);
+       int errorhandler = lua_gettop(L);
+
+       int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, errorhandler);
        if(ret){
-               errorstream<<"Failed to load and run script from "<<path<<": "<<lua_tostring(L, -1)<<std::endl;
+               errorstream<<"========== ERROR FROM LUA ==========="<<std::endl;
+               errorstream<<"Failed to load and run script from "<<std::endl;
+               errorstream<<path<<":"<<std::endl;
+               errorstream<<std::endl;
+               errorstream<<lua_tostring(L, -1)<<std::endl;
+               errorstream<<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;
        }
+       lua_pop(L, 1); // Pop the error handler from stack
        return true;
 }
 
@@ -122,7 +118,7 @@ lua_State* script_init()
        return L;
 }
 
-lua_State* script_deinit(lua_State *L)
+void script_deinit(lua_State *L)
 {
        lua_close(L);
 }