/// An error handler that appends a stack traceback to the error message.
/// Pass this to setErrorHandler to use it.
// Copied from lua-5.0.2/src/lib/ldblib.c
intTracebackErrorHandler( lua_State *L )
{
const int LEVELS1 = 12; /* size of the first part of the stack */
const int LEVELS2 = 10; /* size of the second part of the stack */
int level = 1;/* skip level 0 (it's this function) */
int firstpart = 1;/* still before eventual `...' */
lua_Debug ar;
if (lua_gettop(L) == 0)
lua_pushliteral(L, "");
else if (!lua_isstring(L, 1)) return 1;/* no string message */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
if (!lua_getstack(L, level+LEVELS2, &ar))
level--;/* keep going */
else {
lua_pushliteral(L, "\n\t...");/* too many levels */
while (lua_getstack(L, level+LEVELS2, &ar))/* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n\t");
lua_getinfo(L, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
switch (*ar.namewhat) {
case 'g':/* global */
case 'l':/* local */
case 'f':/* field */
case 'm':/* method */
lua_pushfstring(L, " in function `%s'", ar.name);
break;
default: {
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));
}
lua_concat(L, lua_gettop(L));
return 1;
}