/// 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; }