diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/lua/rocklua.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/apps/plugins/lua/rocklua.c b/apps/plugins/lua/rocklua.c index fcc8a3f9c8..5360090cab 100644 --- a/apps/plugins/lua/rocklua.c +++ b/apps/plugins/lua/rocklua.c | |||
@@ -46,6 +46,95 @@ static void rocklua_openlibs(lua_State *L) { | |||
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | /* ldlib.c */ | ||
50 | static lua_State *getthread (lua_State *L, int *arg) { | ||
51 | if (lua_isthread(L, 1)) { | ||
52 | *arg = 1; | ||
53 | return lua_tothread(L, 1); | ||
54 | } | ||
55 | else { | ||
56 | *arg = 0; | ||
57 | return L; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | #define LEVELS1 12 /* size of the first part of the stack */ | ||
62 | #define LEVELS2 10 /* size of the second part of the stack */ | ||
63 | |||
64 | static int db_errorfb (lua_State *L) { | ||
65 | int level; | ||
66 | int firstpart = 1; /* still before eventual `...' */ | ||
67 | int arg; | ||
68 | lua_State *L1 = getthread(L, &arg); | ||
69 | lua_Debug ar; | ||
70 | if (lua_isnumber(L, arg+2)) { | ||
71 | level = (int)lua_tointeger(L, arg+2); | ||
72 | lua_pop(L, 1); | ||
73 | } | ||
74 | else | ||
75 | level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ | ||
76 | if (lua_gettop(L) == arg) | ||
77 | lua_pushliteral(L, ""); | ||
78 | else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ | ||
79 | else lua_pushliteral(L, "\n"); | ||
80 | lua_pushliteral(L, "stack traceback:"); | ||
81 | while (lua_getstack(L1, level++, &ar)) { | ||
82 | if (level > LEVELS1 && firstpart) { | ||
83 | /* no more than `LEVELS2' more levels? */ | ||
84 | if (!lua_getstack(L1, level+LEVELS2, &ar)) | ||
85 | level--; /* keep going */ | ||
86 | else { | ||
87 | lua_pushliteral(L, "\n\t..."); /* too many levels */ | ||
88 | while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ | ||
89 | level++; | ||
90 | } | ||
91 | firstpart = 0; | ||
92 | continue; | ||
93 | } | ||
94 | lua_pushliteral(L, "\n\t"); | ||
95 | lua_getinfo(L1, "Snl", &ar); | ||
96 | lua_pushfstring(L, "%s:", ar.short_src); | ||
97 | if (ar.currentline > 0) | ||
98 | lua_pushfstring(L, "%d:", ar.currentline); | ||
99 | if (*ar.namewhat != '\0') /* is there a name? */ | ||
100 | lua_pushfstring(L, " in function " LUA_QS, ar.name); | ||
101 | else { | ||
102 | if (*ar.what == 'm') /* main? */ | ||
103 | lua_pushfstring(L, " in main chunk"); | ||
104 | else if (*ar.what == 'C' || *ar.what == 't') | ||
105 | lua_pushliteral(L, " ?"); /* C function or tail call */ | ||
106 | else | ||
107 | lua_pushfstring(L, " in function <%s:%d>", | ||
108 | ar.short_src, ar.linedefined); | ||
109 | } | ||
110 | lua_concat(L, lua_gettop(L) - arg); | ||
111 | } | ||
112 | lua_concat(L, lua_gettop(L) - arg); | ||
113 | return 1; | ||
114 | } | ||
115 | |||
116 | /* lua.c */ | ||
117 | static int traceback (lua_State *L) { | ||
118 | lua_pushcfunction(L, db_errorfb); | ||
119 | lua_pushvalue(L, 1); /* pass error message */ | ||
120 | lua_pushinteger(L, 2); /* skip this function and traceback */ | ||
121 | lua_call(L, 2, 1); /* call debug.traceback */ | ||
122 | return 1; | ||
123 | } | ||
124 | |||
125 | static int docall (lua_State *L) { | ||
126 | int status; | ||
127 | int base = lua_gettop(L); /* function index */ | ||
128 | lua_pushcfunction(L, traceback); /* push traceback function */ | ||
129 | lua_insert(L, base); /* put it under chunk and args */ | ||
130 | status = lua_pcall(L, 0, 0, base); | ||
131 | lua_remove(L, base); /* remove traceback function */ | ||
132 | /* force a complete garbage collection in case of errors */ | ||
133 | if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); | ||
134 | return status; | ||
135 | } | ||
136 | |||
137 | |||
49 | /***************** Plugin Entry Point *****************/ | 138 | /***************** Plugin Entry Point *****************/ |
50 | enum plugin_status plugin_start(const void* parameter) | 139 | enum plugin_status plugin_start(const void* parameter) |
51 | { | 140 | { |
@@ -69,7 +158,7 @@ enum plugin_status plugin_start(const void* parameter) | |||
69 | status = luaL_loadfile(L, filename); | 158 | status = luaL_loadfile(L, filename); |
70 | if (!status) { | 159 | if (!status) { |
71 | rb->lcd_clear_display(); | 160 | rb->lcd_clear_display(); |
72 | status = lua_pcall(L, 0, 0, 0); | 161 | status = docall(L); |
73 | } | 162 | } |
74 | 163 | ||
75 | dlmalloc_stats(); | 164 | dlmalloc_stats(); |