mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
From Lua 5.2: Add luaL_traceback().
This commit is contained in:
parent
3ad61689cf
commit
fcddd5a3a0
@ -82,6 +82,8 @@ LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
|||||||
const char *mode);
|
const char *mode);
|
||||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||||
const char *name, const char *mode);
|
const char *name, const char *mode);
|
||||||
|
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||||
|
int level);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -320,7 +320,7 @@ LJLIB_ASM(tostring) LJLIB_REC(.)
|
|||||||
s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
|
s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
|
||||||
} else {
|
} else {
|
||||||
if (tvisfunc(o) && isffunc(funcV(o)))
|
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
|
else
|
||||||
lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1));
|
lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1));
|
||||||
/* Note: lua_pushfstring calls the GC which may invalidate o. */
|
/* Note: lua_pushfstring calls the GC which may invalidate o. */
|
||||||
|
@ -383,55 +383,13 @@ LJLIB_CF(debug_debug)
|
|||||||
|
|
||||||
LJLIB_CF(debug_traceback)
|
LJLIB_CF(debug_traceback)
|
||||||
{
|
{
|
||||||
int level;
|
|
||||||
int firstpart = 1; /* still before eventual `...' */
|
|
||||||
int arg;
|
int arg;
|
||||||
lua_State *L1 = getthread(L, &arg);
|
lua_State *L1 = getthread(L, &arg);
|
||||||
lua_Debug ar;
|
const char *msg = lua_tostring(L, arg+1);
|
||||||
if (lua_isnumber(L, arg+2)) {
|
if (msg == NULL && L->top > L->base+arg)
|
||||||
level = (int)lua_tointeger(L, arg+2);
|
L->top = L->base+arg+1;
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
|
luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
|
||||||
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);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
14
src/luajit.c
14
src/luajit.c
@ -106,19 +106,7 @@ static int traceback(lua_State *L)
|
|||||||
return 1; /* Return non-string error object. */
|
return 1; /* Return non-string error object. */
|
||||||
lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */
|
lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */
|
||||||
}
|
}
|
||||||
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
|
luaL_traceback(L, L, lua_tostring(L, 1), 1);
|
||||||
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(). */
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user