From fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 1 Oct 2012 20:45:30 +0200 Subject: [PATCH] From Lua 5.2: Add luaL_traceback(). --- src/lauxlib.h | 2 ++ src/lib_base.c | 2 +- src/lib_debug.c | 50 ++++---------------------------------------------- src/lj_debug.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/luajit.c | 14 +------------- 5 files changed, 59 insertions(+), 60 deletions(-) diff --git a/src/lauxlib.h b/src/lauxlib.h index b0f66d68..fed1491b 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -82,6 +82,8 @@ LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, + int level); /* diff --git a/src/lib_base.c b/src/lib_base.c index 6f664eb6..568216e1 100644 --- a/src/lib_base.c +++ b/src/lib_base.c @@ -320,7 +320,7 @@ LJLIB_ASM(tostring) LJLIB_REC(.) s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); } else { if (tvisfunc(o) && isffunc(funcV(o))) - lua_pushfstring(L, "function: fast#%d", funcV(o)->c.ffid); + lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid); else lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1)); /* Note: lua_pushfstring calls the GC which may invalidate o. */ diff --git a/src/lib_debug.c b/src/lib_debug.c index 07b025af..06750266 100644 --- a/src/lib_debug.c +++ b/src/lib_debug.c @@ -383,55 +383,13 @@ LJLIB_CF(debug_debug) LJLIB_CF(debug_traceback) { - int level; - int firstpart = 1; /* still before eventual `...' */ int arg; lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (lua_isnumber(L, arg+2)) { - level = (int)lua_tointeger(L, arg+2); - lua_pop(L, 1); - } + const char *msg = lua_tostring(L, arg+1); + if (msg == NULL && L->top > L->base+arg) + L->top = L->base+arg+1; else - level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ - if (lua_gettop(L) == arg) - lua_pushliteral(L, ""); - else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ - else lua_pushliteral(L, "\n"); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level > LEVELS1 && firstpart) { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L1, level+LEVELS2, &ar)) { - level--; /* keep going */ - } else { - lua_pushliteral(L, "\n\t..."); /* too many levels */ - /* This only works with LuaJIT 2.x. Avoids O(n^2) behaviour. */ - lua_getstack(L1, -10, &ar); - level = ar.i_ci - LEVELS2; - } - firstpart = 0; - continue; - } - lua_pushliteral(L, "\n\t"); - lua_getinfo(L1, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - if (*ar.namewhat != '\0') { /* is there a name? */ - lua_pushfstring(L, " in function " LUA_QS, ar.name); - } else { - if (*ar.what == 'm') /* main? */ - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C' || *ar.what == 't') - lua_pushliteral(L, " ?"); /* C function or tail call */ - else - lua_pushfstring(L, " in function <%s:%d>", - ar.short_src, ar.linedefined); - } - lua_concat(L, lua_gettop(L) - arg); - } - lua_concat(L, lua_gettop(L) - arg); + luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1))); return 1; } diff --git a/src/lj_debug.c b/src/lj_debug.c index 0e26cd7c..4f4c4bb1 100644 --- a/src/lj_debug.c +++ b/src/lj_debug.c @@ -543,3 +543,54 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar) } } +/* Number of frames for the leading and trailing part of a traceback. */ +#define TRACEBACK_LEVELS1 12 +#define TRACEBACK_LEVELS2 10 + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, + int level) +{ + int top = (int)(L->top - L->base); + int lim = TRACEBACK_LEVELS1; + lua_Debug ar; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + GCfunc *fn; + if (level > lim) { + if (!lua_getstack(L1, level + TRACEBACK_LEVELS2, &ar)) { + level--; + } else { + lua_pushliteral(L, "\n\t..."); + lua_getstack(L1, -10, &ar); + level = ar.i_ci - TRACEBACK_LEVELS2; + } + lim = 2147483647; + continue; + } + lua_getinfo(L1, "Snlf", &ar); + fn = funcV(L1->top-1); L1->top--; + if (isffunc(fn) && !*ar.namewhat) + lua_pushfstring(L, "\n\t[builtin#%d]:", fn->c.ffid); + else + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + if (*ar.namewhat) { + lua_pushfstring(L, " in function " LUA_QS, ar.name); + } else { + if (*ar.what == 'm') { + lua_pushliteral(L, " in main chunk"); + } else if (*ar.what == 'C') { + lua_pushfstring(L, " at %p", fn->c.f); + } else { + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + } + if ((int)(L->top - L->base) - top >= 15) + lua_concat(L, (int)(L->top - L->base) - top); + } + lua_concat(L, (int)(L->top - L->base) - top); +} + diff --git a/src/luajit.c b/src/luajit.c index 22628aaf..a9476372 100644 --- a/src/luajit.c +++ b/src/luajit.c @@ -106,19 +106,7 @@ static int traceback(lua_State *L) return 1; /* Return non-string error object. */ lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ } - 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); /* Push error message. */ - lua_pushinteger(L, 2); /* Skip this function and debug.traceback(). */ - lua_call(L, 2, 1); /* Call debug.traceback(). */ + luaL_traceback(L, L, lua_tostring(L, 1), 1); return 1; } -- 2.11.4.GIT