]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Lua/src/ldblib.c
AppPkg: Add the Lua interpreter and library.
[mirror_edk2.git] / AppPkg / Applications / Lua / src / ldblib.c
CommitLineData
16a5fed6 1/*\r
2** $Id: ldblib.c,v 1.132.1.1 2013/04/12 18:48:47 roberto Exp $\r
3** Interface from Lua to its debug API\r
4** See Copyright Notice in lua.h\r
5*/\r
6\r
7\r
8#include <stdio.h>\r
9#include <stdlib.h>\r
10#include <string.h>\r
11\r
12#define ldblib_c\r
13#define LUA_LIB\r
14\r
15#include "lua.h"\r
16\r
17#include "lauxlib.h"\r
18#include "lualib.h"\r
19\r
20\r
21#define HOOKKEY "_HKEY"\r
22\r
23\r
24\r
25static int db_getregistry (lua_State *L) {\r
26 lua_pushvalue(L, LUA_REGISTRYINDEX);\r
27 return 1;\r
28}\r
29\r
30\r
31static int db_getmetatable (lua_State *L) {\r
32 luaL_checkany(L, 1);\r
33 if (!lua_getmetatable(L, 1)) {\r
34 lua_pushnil(L); /* no metatable */\r
35 }\r
36 return 1;\r
37}\r
38\r
39\r
40static int db_setmetatable (lua_State *L) {\r
41 int t = lua_type(L, 2);\r
42 luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\r
43 "nil or table expected");\r
44 lua_settop(L, 2);\r
45 lua_setmetatable(L, 1);\r
46 return 1; /* return 1st argument */\r
47}\r
48\r
49\r
50static int db_getuservalue (lua_State *L) {\r
51 if (lua_type(L, 1) != LUA_TUSERDATA)\r
52 lua_pushnil(L);\r
53 else\r
54 lua_getuservalue(L, 1);\r
55 return 1;\r
56}\r
57\r
58\r
59static int db_setuservalue (lua_State *L) {\r
60 if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)\r
61 luaL_argerror(L, 1, "full userdata expected, got light userdata");\r
62 luaL_checktype(L, 1, LUA_TUSERDATA);\r
63 if (!lua_isnoneornil(L, 2))\r
64 luaL_checktype(L, 2, LUA_TTABLE);\r
65 lua_settop(L, 2);\r
66 lua_setuservalue(L, 1);\r
67 return 1;\r
68}\r
69\r
70\r
71static void settabss (lua_State *L, const char *i, const char *v) {\r
72 lua_pushstring(L, v);\r
73 lua_setfield(L, -2, i);\r
74}\r
75\r
76\r
77static void settabsi (lua_State *L, const char *i, int v) {\r
78 lua_pushinteger(L, v);\r
79 lua_setfield(L, -2, i);\r
80}\r
81\r
82\r
83static void settabsb (lua_State *L, const char *i, int v) {\r
84 lua_pushboolean(L, v);\r
85 lua_setfield(L, -2, i);\r
86}\r
87\r
88\r
89static lua_State *getthread (lua_State *L, int *arg) {\r
90 if (lua_isthread(L, 1)) {\r
91 *arg = 1;\r
92 return lua_tothread(L, 1);\r
93 }\r
94 else {\r
95 *arg = 0;\r
96 return L;\r
97 }\r
98}\r
99\r
100\r
101static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {\r
102 if (L == L1) {\r
103 lua_pushvalue(L, -2);\r
104 lua_remove(L, -3);\r
105 }\r
106 else\r
107 lua_xmove(L1, L, 1);\r
108 lua_setfield(L, -2, fname);\r
109}\r
110\r
111\r
112static int db_getinfo (lua_State *L) {\r
113 lua_Debug ar;\r
114 int arg;\r
115 lua_State *L1 = getthread(L, &arg);\r
116 const char *options = luaL_optstring(L, arg+2, "flnStu");\r
117 if (lua_isnumber(L, arg+1)) {\r
118 if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {\r
119 lua_pushnil(L); /* level out of range */\r
120 return 1;\r
121 }\r
122 }\r
123 else if (lua_isfunction(L, arg+1)) {\r
124 lua_pushfstring(L, ">%s", options);\r
125 options = lua_tostring(L, -1);\r
126 lua_pushvalue(L, arg+1);\r
127 lua_xmove(L, L1, 1);\r
128 }\r
129 else\r
130 return luaL_argerror(L, arg+1, "function or level expected");\r
131 if (!lua_getinfo(L1, options, &ar))\r
132 return luaL_argerror(L, arg+2, "invalid option");\r
133 lua_createtable(L, 0, 2);\r
134 if (strchr(options, 'S')) {\r
135 settabss(L, "source", ar.source);\r
136 settabss(L, "short_src", ar.short_src);\r
137 settabsi(L, "linedefined", ar.linedefined);\r
138 settabsi(L, "lastlinedefined", ar.lastlinedefined);\r
139 settabss(L, "what", ar.what);\r
140 }\r
141 if (strchr(options, 'l'))\r
142 settabsi(L, "currentline", ar.currentline);\r
143 if (strchr(options, 'u')) {\r
144 settabsi(L, "nups", ar.nups);\r
145 settabsi(L, "nparams", ar.nparams);\r
146 settabsb(L, "isvararg", ar.isvararg);\r
147 }\r
148 if (strchr(options, 'n')) {\r
149 settabss(L, "name", ar.name);\r
150 settabss(L, "namewhat", ar.namewhat);\r
151 }\r
152 if (strchr(options, 't'))\r
153 settabsb(L, "istailcall", ar.istailcall);\r
154 if (strchr(options, 'L'))\r
155 treatstackoption(L, L1, "activelines");\r
156 if (strchr(options, 'f'))\r
157 treatstackoption(L, L1, "func");\r
158 return 1; /* return table */\r
159}\r
160\r
161\r
162static int db_getlocal (lua_State *L) {\r
163 int arg;\r
164 lua_State *L1 = getthread(L, &arg);\r
165 lua_Debug ar;\r
166 const char *name;\r
167 int nvar = luaL_checkint(L, arg+2); /* local-variable index */\r
168 if (lua_isfunction(L, arg + 1)) { /* function argument? */\r
169 lua_pushvalue(L, arg + 1); /* push function */\r
170 lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */\r
171 return 1;\r
172 }\r
173 else { /* stack-level argument */\r
174 if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */\r
175 return luaL_argerror(L, arg+1, "level out of range");\r
176 name = lua_getlocal(L1, &ar, nvar);\r
177 if (name) {\r
178 lua_xmove(L1, L, 1); /* push local value */\r
179 lua_pushstring(L, name); /* push name */\r
180 lua_pushvalue(L, -2); /* re-order */\r
181 return 2;\r
182 }\r
183 else {\r
184 lua_pushnil(L); /* no name (nor value) */\r
185 return 1;\r
186 }\r
187 }\r
188}\r
189\r
190\r
191static int db_setlocal (lua_State *L) {\r
192 int arg;\r
193 lua_State *L1 = getthread(L, &arg);\r
194 lua_Debug ar;\r
195 if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */\r
196 return luaL_argerror(L, arg+1, "level out of range");\r
197 luaL_checkany(L, arg+3);\r
198 lua_settop(L, arg+3);\r
199 lua_xmove(L, L1, 1);\r
200 lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));\r
201 return 1;\r
202}\r
203\r
204\r
205static int auxupvalue (lua_State *L, int get) {\r
206 const char *name;\r
207 int n = luaL_checkint(L, 2);\r
208 luaL_checktype(L, 1, LUA_TFUNCTION);\r
209 name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);\r
210 if (name == NULL) return 0;\r
211 lua_pushstring(L, name);\r
212 lua_insert(L, -(get+1));\r
213 return get + 1;\r
214}\r
215\r
216\r
217static int db_getupvalue (lua_State *L) {\r
218 return auxupvalue(L, 1);\r
219}\r
220\r
221\r
222static int db_setupvalue (lua_State *L) {\r
223 luaL_checkany(L, 3);\r
224 return auxupvalue(L, 0);\r
225}\r
226\r
227\r
228static int checkupval (lua_State *L, int argf, int argnup) {\r
229 lua_Debug ar;\r
230 int nup = luaL_checkint(L, argnup);\r
231 luaL_checktype(L, argf, LUA_TFUNCTION);\r
232 lua_pushvalue(L, argf);\r
233 lua_getinfo(L, ">u", &ar);\r
234 luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");\r
235 return nup;\r
236}\r
237\r
238\r
239static int db_upvalueid (lua_State *L) {\r
240 int n = checkupval(L, 1, 2);\r
241 lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));\r
242 return 1;\r
243}\r
244\r
245\r
246static int db_upvaluejoin (lua_State *L) {\r
247 int n1 = checkupval(L, 1, 2);\r
248 int n2 = checkupval(L, 3, 4);\r
249 luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");\r
250 luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");\r
251 lua_upvaluejoin(L, 1, n1, 3, n2);\r
252 return 0;\r
253}\r
254\r
255\r
256#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)\r
257\r
258\r
259static void hookf (lua_State *L, lua_Debug *ar) {\r
260 static const char *const hooknames[] =\r
261 {"call", "return", "line", "count", "tail call"};\r
262 gethooktable(L);\r
263 lua_pushthread(L);\r
264 lua_rawget(L, -2);\r
265 if (lua_isfunction(L, -1)) {\r
266 lua_pushstring(L, hooknames[(int)ar->event]);\r
267 if (ar->currentline >= 0)\r
268 lua_pushinteger(L, ar->currentline);\r
269 else lua_pushnil(L);\r
270 lua_assert(lua_getinfo(L, "lS", ar));\r
271 lua_call(L, 2, 0);\r
272 }\r
273}\r
274\r
275\r
276static int makemask (const char *smask, int count) {\r
277 int mask = 0;\r
278 if (strchr(smask, 'c')) mask |= LUA_MASKCALL;\r
279 if (strchr(smask, 'r')) mask |= LUA_MASKRET;\r
280 if (strchr(smask, 'l')) mask |= LUA_MASKLINE;\r
281 if (count > 0) mask |= LUA_MASKCOUNT;\r
282 return mask;\r
283}\r
284\r
285\r
286static char *unmakemask (int mask, char *smask) {\r
287 int i = 0;\r
288 if (mask & LUA_MASKCALL) smask[i++] = 'c';\r
289 if (mask & LUA_MASKRET) smask[i++] = 'r';\r
290 if (mask & LUA_MASKLINE) smask[i++] = 'l';\r
291 smask[i] = '\0';\r
292 return smask;\r
293}\r
294\r
295\r
296static int db_sethook (lua_State *L) {\r
297 int arg, mask, count;\r
298 lua_Hook func;\r
299 lua_State *L1 = getthread(L, &arg);\r
300 if (lua_isnoneornil(L, arg+1)) {\r
301 lua_settop(L, arg+1);\r
302 func = NULL; mask = 0; count = 0; /* turn off hooks */\r
303 }\r
304 else {\r
305 const char *smask = luaL_checkstring(L, arg+2);\r
306 luaL_checktype(L, arg+1, LUA_TFUNCTION);\r
307 count = luaL_optint(L, arg+3, 0);\r
308 func = hookf; mask = makemask(smask, count);\r
309 }\r
310 if (gethooktable(L) == 0) { /* creating hook table? */\r
311 lua_pushstring(L, "k");\r
312 lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */\r
313 lua_pushvalue(L, -1);\r
314 lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */\r
315 }\r
316 lua_pushthread(L1); lua_xmove(L1, L, 1);\r
317 lua_pushvalue(L, arg+1);\r
318 lua_rawset(L, -3); /* set new hook */\r
319 lua_sethook(L1, func, mask, count); /* set hooks */\r
320 return 0;\r
321}\r
322\r
323\r
324static int db_gethook (lua_State *L) {\r
325 int arg;\r
326 lua_State *L1 = getthread(L, &arg);\r
327 char buff[5];\r
328 int mask = lua_gethookmask(L1);\r
329 lua_Hook hook = lua_gethook(L1);\r
330 if (hook != NULL && hook != hookf) /* external hook? */\r
331 lua_pushliteral(L, "external hook");\r
332 else {\r
333 gethooktable(L);\r
334 lua_pushthread(L1); lua_xmove(L1, L, 1);\r
335 lua_rawget(L, -2); /* get hook */\r
336 lua_remove(L, -2); /* remove hook table */\r
337 }\r
338 lua_pushstring(L, unmakemask(mask, buff));\r
339 lua_pushinteger(L, lua_gethookcount(L1));\r
340 return 3;\r
341}\r
342\r
343\r
344static int db_debug (lua_State *L) {\r
345 for (;;) {\r
346 char buffer[250];\r
347 luai_writestringerror("%s", "lua_debug> ");\r
348 if (fgets(buffer, sizeof(buffer), stdin) == 0 ||\r
349 strcmp(buffer, "cont\n") == 0)\r
350 return 0;\r
351 if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||\r
352 lua_pcall(L, 0, 0, 0))\r
353 luai_writestringerror("%s\n", lua_tostring(L, -1));\r
354 lua_settop(L, 0); /* remove eventual returns */\r
355 }\r
356}\r
357\r
358\r
359static int db_traceback (lua_State *L) {\r
360 int arg;\r
361 lua_State *L1 = getthread(L, &arg);\r
362 const char *msg = lua_tostring(L, arg + 1);\r
363 if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */\r
364 lua_pushvalue(L, arg + 1); /* return it untouched */\r
365 else {\r
366 int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);\r
367 luaL_traceback(L, L1, msg, level);\r
368 }\r
369 return 1;\r
370}\r
371\r
372\r
373static const luaL_Reg dblib[] = {\r
374 {"debug", db_debug},\r
375 {"getuservalue", db_getuservalue},\r
376 {"gethook", db_gethook},\r
377 {"getinfo", db_getinfo},\r
378 {"getlocal", db_getlocal},\r
379 {"getregistry", db_getregistry},\r
380 {"getmetatable", db_getmetatable},\r
381 {"getupvalue", db_getupvalue},\r
382 {"upvaluejoin", db_upvaluejoin},\r
383 {"upvalueid", db_upvalueid},\r
384 {"setuservalue", db_setuservalue},\r
385 {"sethook", db_sethook},\r
386 {"setlocal", db_setlocal},\r
387 {"setmetatable", db_setmetatable},\r
388 {"setupvalue", db_setupvalue},\r
389 {"traceback", db_traceback},\r
390 {NULL, NULL}\r
391};\r
392\r
393\r
394LUAMOD_API int luaopen_debug (lua_State *L) {\r
395 luaL_newlib(L, dblib);\r
396 return 1;\r
397}\r
398\r