gateway: simplify stopping the cleanup timer
[olsrd.git] / lib / tas / src / lua / ldblib.c
1
2 /*
3 ** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 roberto Exp $
4 ** Interface from Lua to its debug API
5 ** See Copyright Notice in lua.h
6 */
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #define ldblib_c
14
15 #include "lua.h"
16
17 #include "lauxlib.h"
18 #include "lualib.h"
19
20
21
22 static void
23 settabss(lua_State * L, const char *i, const char *v)
24 {
25   lua_pushstring(L, i);
26   lua_pushstring(L, v);
27   lua_rawset(L, -3);
28 }
29
30
31 static void
32 settabsi(lua_State * L, const char *i, int v)
33 {
34   lua_pushstring(L, i);
35   lua_pushnumber(L, (lua_Number) v);
36   lua_rawset(L, -3);
37 }
38
39
40 static int
41 getinfo(lua_State * L)
42 {
43   lua_Debug ar;
44   const char *options = luaL_optstring(L, 2, "flnSu");
45   if (lua_isnumber(L, 1)) {
46     if (!lua_getstack(L, lua_tonumber(L, 1), &ar)) {
47       lua_pushnil(L);           /* level out of range */
48       return 1;
49     }
50   } else if (lua_isfunction(L, 1)) {
51     lua_pushfstring(L, ">%s", options);
52     options = lua_tostring(L, -1);
53     lua_pushvalue(L, 1);
54   } else
55     return luaL_argerror(L, 1, "function or level expected");
56   if (!lua_getinfo(L, options, &ar))
57     return luaL_argerror(L, 2, "invalid option");
58   lua_newtable(L);
59   for (; *options; options++) {
60     switch (*options) {
61     case 'S':
62       settabss(L, "source", ar.source);
63       settabss(L, "short_src", ar.short_src);
64       settabsi(L, "linedefined", ar.linedefined);
65       settabss(L, "what", ar.what);
66       break;
67     case 'l':
68       settabsi(L, "currentline", ar.currentline);
69       break;
70     case 'u':
71       settabsi(L, "nups", ar.nups);
72       break;
73     case 'n':
74       settabss(L, "name", ar.name);
75       settabss(L, "namewhat", ar.namewhat);
76       break;
77     case 'f':
78       lua_pushliteral(L, "func");
79       lua_pushvalue(L, -3);
80       lua_rawset(L, -3);
81       break;
82     }
83   }
84   return 1;                     /* return table */
85 }
86
87
88 static int
89 getlocal(lua_State * L)
90 {
91   lua_Debug ar;
92   const char *name;
93   if (!lua_getstack(L, luaL_checkint(L, 1), &ar))       /* level out of range? */
94     return luaL_argerror(L, 1, "level out of range");
95   name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
96   if (name) {
97     lua_pushstring(L, name);
98     lua_pushvalue(L, -2);
99     return 2;
100   } else {
101     lua_pushnil(L);
102     return 1;
103   }
104 }
105
106
107 static int
108 setlocal(lua_State * L)
109 {
110   lua_Debug ar;
111   if (!lua_getstack(L, luaL_checkint(L, 1), &ar))       /* level out of range? */
112     return luaL_argerror(L, 1, "level out of range");
113   luaL_checkany(L, 3);
114   lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
115   return 1;
116 }
117
118
119 static int
120 auxupvalue(lua_State * L, int get)
121 {
122   const char *name;
123   int n = luaL_checkint(L, 2);
124   luaL_checktype(L, 1, LUA_TFUNCTION);
125   if (lua_iscfunction(L, 1))
126     return 0;                   /* cannot touch C upvalues from Lua */
127   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
128   if (name == NULL)
129     return 0;
130   lua_pushstring(L, name);
131   lua_insert(L, -(get + 1));
132   return get + 1;
133 }
134
135
136 static int
137 getupvalue(lua_State * L)
138 {
139   return auxupvalue(L, 1);
140 }
141
142
143 static int
144 setupvalue(lua_State * L)
145 {
146   luaL_checkany(L, 3);
147   return auxupvalue(L, 0);
148 }
149
150
151
152 static const char KEY_HOOK = 'h';
153
154
155 static void
156 hookf(lua_State * L, lua_Debug * ar)
157 {
158   static const char *const hooknames[] = { "call", "return", "line", "count", "tail return" };
159   lua_pushlightuserdata(L, &KEY_HOOK);
160   lua_rawget(L, LUA_REGISTRYINDEX);
161   if (lua_isfunction(L, -1)) {
162     lua_pushstring(L, hooknames[(int)ar->event]);
163     if (ar->currentline >= 0)
164       lua_pushnumber(L, (lua_Number) ar->currentline);
165     else
166       lua_pushnil(L);
167     lua_assert(lua_getinfo(L, "lS", ar));
168     lua_call(L, 2, 0);
169   } else
170     lua_pop(L, 1);              /* pop result from gettable */
171 }
172
173
174 static int
175 makemask(const char *smask, int count)
176 {
177   int mask = 0;
178   if (strchr(smask, 'c'))
179     mask |= LUA_MASKCALL;
180   if (strchr(smask, 'r'))
181     mask |= LUA_MASKRET;
182   if (strchr(smask, 'l'))
183     mask |= LUA_MASKLINE;
184   if (count > 0)
185     mask |= LUA_MASKCOUNT;
186   return mask;
187 }
188
189
190 static char *
191 unmakemask(int mask, char *smask)
192 {
193   int i = 0;
194   if (mask & LUA_MASKCALL)
195     smask[i++] = 'c';
196   if (mask & LUA_MASKRET)
197     smask[i++] = 'r';
198   if (mask & LUA_MASKLINE)
199     smask[i++] = 'l';
200   smask[i] = '\0';
201   return smask;
202 }
203
204
205 static int
206 sethook(lua_State * L)
207 {
208   if (lua_isnoneornil(L, 1)) {
209     lua_settop(L, 1);
210     lua_sethook(L, NULL, 0, 0); /* turn off hooks */
211   } else {
212     const char *smask = luaL_checkstring(L, 2);
213     int count = luaL_optint(L, 3, 0);
214     luaL_checktype(L, 1, LUA_TFUNCTION);
215     lua_sethook(L, hookf, makemask(smask, count), count);
216   }
217   lua_pushlightuserdata(L, &KEY_HOOK);
218   lua_pushvalue(L, 1);
219   lua_rawset(L, LUA_REGISTRYINDEX);     /* set new hook */
220   return 0;
221 }
222
223
224 static int
225 gethook(lua_State * L)
226 {
227   char buff[5];
228   int mask = lua_gethookmask(L);
229   lua_Hook hook = lua_gethook(L);
230   if (hook != NULL && hook != hookf)    /* external hook? */
231     lua_pushliteral(L, "external hook");
232   else {
233     lua_pushlightuserdata(L, &KEY_HOOK);
234     lua_rawget(L, LUA_REGISTRYINDEX);   /* get hook */
235   }
236   lua_pushstring(L, unmakemask(mask, buff));
237   lua_pushnumber(L, lua_gethookcount(L));
238   return 3;
239 }
240
241
242 static int
243 debug(lua_State * L)
244 {
245   for (;;) {
246     char buffer[250];
247     fputs("lua_debug> ", stderr);
248     if (fgets(buffer, sizeof(buffer), stdin) == 0 || strcmp(buffer, "cont\n") == 0)
249       return 0;
250     lua_dostring(L, buffer);
251     lua_settop(L, 0);           /* remove eventual returns */
252   }
253 }
254
255
256 #define LEVELS1 12              /* size of the first part of the stack */
257 #define LEVELS2 10              /* size of the second part of the stack */
258
259 static int
260 errorfb(lua_State * L)
261 {
262   int level = 1;                       /* skip level 0 (it's this function) */
263   int firstpart = 1;                   /* still before eventual `...' */
264   lua_Debug ar;
265   if (lua_gettop(L) == 0)
266     lua_pushliteral(L, "");
267   else if (!lua_isstring(L, 1))
268     return 1;                   /* no string message */
269   else
270     lua_pushliteral(L, "\n");
271   lua_pushliteral(L, "stack traceback:");
272   while (lua_getstack(L, level++, &ar)) {
273     if (level > LEVELS1 && firstpart) {
274       /* no more than `LEVELS2' more levels? */
275       if (!lua_getstack(L, level + LEVELS2, &ar))
276         level--;                /* keep going */
277       else {
278         lua_pushliteral(L, "\n\t...");  /* too many levels */
279         while (lua_getstack(L, level + LEVELS2, &ar))   /* find last levels */
280           level++;
281       }
282       firstpart = 0;
283       continue;
284     }
285     lua_pushliteral(L, "\n\t");
286     lua_getinfo(L, "Snl", &ar);
287     lua_pushfstring(L, "%s:", ar.short_src);
288     if (ar.currentline > 0)
289       lua_pushfstring(L, "%d:", ar.currentline);
290     switch (*ar.namewhat) {
291     case 'g':                  /* global */
292     case 'l':                  /* local */
293     case 'f':                  /* field */
294     case 'm':                  /* method */
295       lua_pushfstring(L, " in function `%s'", ar.name);
296       break;
297     default:{
298         if (*ar.what == 'm')    /* main? */
299           lua_pushfstring(L, " in main chunk");
300         else if (*ar.what == 'C' || *ar.what == 't')
301           lua_pushliteral(L, " ?");     /* C function or tail call */
302         else
303           lua_pushfstring(L, " in function <%s:%d>", ar.short_src, ar.linedefined);
304       }
305     }
306     lua_concat(L, lua_gettop(L));
307   }
308   lua_concat(L, lua_gettop(L));
309   return 1;
310 }
311
312
313 static const luaL_reg dblib[] = {
314   {"getlocal", getlocal},
315   {"getinfo", getinfo},
316   {"gethook", gethook},
317   {"getupvalue", getupvalue},
318   {"sethook", sethook},
319   {"setlocal", setlocal},
320   {"setupvalue", setupvalue},
321   {"debug", debug},
322   {"traceback", errorfb},
323   {NULL, NULL}
324 };
325
326
327 LUALIB_API int
328 luaopen_debug(lua_State * L)
329 {
330   luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
331   lua_pushliteral(L, "_TRACEBACK");
332   lua_pushcfunction(L, errorfb);
333   lua_settable(L, LUA_GLOBALSINDEX);
334   return 1;
335 }