]>
Commit | Line | Data |
---|---|---|
f9f8ee13 CP |
1 | #include <lua.h> |
2 | #include <lauxlib.h> | |
3 | #include <lualib.h> | |
4 | ||
5 | #define LEVELS1 12 /* size of the first part of the stack */ | |
6 | #define LEVELS2 10 /* size of the second part of the stack */ | |
7 | ||
8 | /* stolen from ldblib.c as I can't figure out how to import it! */ | |
9 | ||
10 | static lua_State *getthread (lua_State *L, int *arg) { | |
11 | if (lua_isthread(L, 1)) { | |
12 | *arg = 1; | |
13 | return lua_tothread(L, 1); | |
14 | } | |
15 | else { | |
16 | *arg = 0; | |
17 | return L; | |
18 | } | |
19 | } | |
20 | ||
21 | static int db_errorfb (lua_State *L) { | |
22 | int level; | |
23 | int firstpart = 1; /* still before eventual `...' */ | |
24 | int arg; | |
25 | lua_State *L1 = getthread(L, &arg); | |
26 | lua_Debug ar; | |
27 | if (lua_isnumber(L, arg+2)) { | |
28 | level = (int)lua_tointeger(L, arg+2); | |
29 | lua_pop(L, 1); | |
30 | } | |
31 | else | |
32 | level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ | |
33 | if (lua_gettop(L) == arg) | |
34 | lua_pushliteral(L, ""); | |
35 | else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ | |
36 | else lua_pushliteral(L, "\n"); | |
37 | ||
38 | lua_pushliteral(L, "stack traceback:"); | |
39 | while (lua_getstack(L1, level++, &ar)) { | |
40 | if (level > LEVELS1 && firstpart) { | |
41 | /* no more than `LEVELS2' more levels? */ | |
42 | if (!lua_getstack(L1, level+LEVELS2, &ar)) | |
43 | level--; /* keep going */ | |
44 | else { | |
45 | lua_pushliteral(L, "\n\t..."); /* too many levels */ | |
46 | while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ | |
47 | level++; | |
48 | } | |
49 | firstpart = 0; | |
50 | continue; | |
51 | } | |
52 | lua_pushliteral(L, "\n\t"); | |
53 | lua_getinfo(L1, "Snl", &ar); | |
54 | lua_pushfstring(L, "%s:", ar.short_src); | |
55 | if (ar.currentline > 0) | |
56 | lua_pushfstring(L, "%d:", ar.currentline); | |
57 | if (*ar.namewhat != '\0') /* is there a name? */ | |
58 | lua_pushfstring(L, " in function " LUA_QS, ar.name); | |
59 | else { | |
60 | if (*ar.what == 'm') /* main? */ | |
61 | lua_pushfstring(L, " in main chunk"); | |
62 | else if (*ar.what == 'C' || *ar.what == 't') | |
63 | lua_pushliteral(L, " ?"); /* C function or tail call */ | |
64 | else | |
65 | lua_pushfstring(L, " in function <%s:%d>", | |
66 | ar.short_src, ar.linedefined); | |
67 | } | |
68 | lua_concat(L, lua_gettop(L) - arg); | |
69 | } | |
70 | lua_concat(L, lua_gettop(L) - arg); | |
71 | return 1; | |
72 | } | |
73 | ||
74 | void lua_registerdebug(lua_State *l) { | |
75 | lua_register(l, "traceback", db_errorfb); | |
76 | } | |
77 |