]>
git.saurik.com Git - redis.git/blob - deps/lua/src/ldblib.c
67de1222a948ca2e20e078d35e2e497bf833a986
2 ** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
3 ** Interface from Lua to its debug API
4 ** See Copyright Notice in lua.h
22 static int db_getregistry (lua_State
*L
) {
23 lua_pushvalue(L
, LUA_REGISTRYINDEX
);
28 static int db_getmetatable (lua_State
*L
) {
30 if (!lua_getmetatable(L
, 1)) {
31 lua_pushnil(L
); /* no metatable */
37 static int db_setmetatable (lua_State
*L
) {
38 int t
= lua_type(L
, 2);
39 luaL_argcheck(L
, t
== LUA_TNIL
|| t
== LUA_TTABLE
, 2,
40 "nil or table expected");
42 lua_pushboolean(L
, lua_setmetatable(L
, 1));
47 static int db_getfenv (lua_State
*L
) {
53 static int db_setfenv (lua_State
*L
) {
54 luaL_checktype(L
, 2, LUA_TTABLE
);
56 if (lua_setfenv(L
, 1) == 0)
57 luaL_error(L
, LUA_QL("setfenv")
58 " cannot change environment of given object");
63 static void settabss (lua_State
*L
, const char *i
, const char *v
) {
65 lua_setfield(L
, -2, i
);
69 static void settabsi (lua_State
*L
, const char *i
, int v
) {
70 lua_pushinteger(L
, v
);
71 lua_setfield(L
, -2, i
);
75 static lua_State
*getthread (lua_State
*L
, int *arg
) {
76 if (lua_isthread(L
, 1)) {
78 return lua_tothread(L
, 1);
87 static void treatstackoption (lua_State
*L
, lua_State
*L1
, const char *fname
) {
94 lua_setfield(L
, -2, fname
);
98 static int db_getinfo (lua_State
*L
) {
101 lua_State
*L1
= getthread(L
, &arg
);
102 const char *options
= luaL_optstring(L
, arg
+2, "flnSu");
103 if (lua_isnumber(L
, arg
+1)) {
104 if (!lua_getstack(L1
, (int)lua_tointeger(L
, arg
+1), &ar
)) {
105 lua_pushnil(L
); /* level out of range */
109 else if (lua_isfunction(L
, arg
+1)) {
110 lua_pushfstring(L
, ">%s", options
);
111 options
= lua_tostring(L
, -1);
112 lua_pushvalue(L
, arg
+1);
116 return luaL_argerror(L
, arg
+1, "function or level expected");
117 if (!lua_getinfo(L1
, options
, &ar
))
118 return luaL_argerror(L
, arg
+2, "invalid option");
119 lua_createtable(L
, 0, 2);
120 if (strchr(options
, 'S')) {
121 settabss(L
, "source", ar
.source
);
122 settabss(L
, "short_src", ar
.short_src
);
123 settabsi(L
, "linedefined", ar
.linedefined
);
124 settabsi(L
, "lastlinedefined", ar
.lastlinedefined
);
125 settabss(L
, "what", ar
.what
);
127 if (strchr(options
, 'l'))
128 settabsi(L
, "currentline", ar
.currentline
);
129 if (strchr(options
, 'u'))
130 settabsi(L
, "nups", ar
.nups
);
131 if (strchr(options
, 'n')) {
132 settabss(L
, "name", ar
.name
);
133 settabss(L
, "namewhat", ar
.namewhat
);
135 if (strchr(options
, 'L'))
136 treatstackoption(L
, L1
, "activelines");
137 if (strchr(options
, 'f'))
138 treatstackoption(L
, L1
, "func");
139 return 1; /* return table */
143 static int db_getlocal (lua_State
*L
) {
145 lua_State
*L1
= getthread(L
, &arg
);
148 if (!lua_getstack(L1
, luaL_checkint(L
, arg
+1), &ar
)) /* out of range? */
149 return luaL_argerror(L
, arg
+1, "level out of range");
150 name
= lua_getlocal(L1
, &ar
, luaL_checkint(L
, arg
+2));
153 lua_pushstring(L
, name
);
154 lua_pushvalue(L
, -2);
164 static int db_setlocal (lua_State
*L
) {
166 lua_State
*L1
= getthread(L
, &arg
);
168 if (!lua_getstack(L1
, luaL_checkint(L
, arg
+1), &ar
)) /* out of range? */
169 return luaL_argerror(L
, arg
+1, "level out of range");
170 luaL_checkany(L
, arg
+3);
171 lua_settop(L
, arg
+3);
173 lua_pushstring(L
, lua_setlocal(L1
, &ar
, luaL_checkint(L
, arg
+2)));
178 static int auxupvalue (lua_State
*L
, int get
) {
180 int n
= luaL_checkint(L
, 2);
181 luaL_checktype(L
, 1, LUA_TFUNCTION
);
182 if (lua_iscfunction(L
, 1)) return 0; /* cannot touch C upvalues from Lua */
183 name
= get
? lua_getupvalue(L
, 1, n
) : lua_setupvalue(L
, 1, n
);
184 if (name
== NULL
) return 0;
185 lua_pushstring(L
, name
);
186 lua_insert(L
, -(get
+1));
191 static int db_getupvalue (lua_State
*L
) {
192 return auxupvalue(L
, 1);
196 static int db_setupvalue (lua_State
*L
) {
198 return auxupvalue(L
, 0);
203 static const char KEY_HOOK
= 'h';
206 static void hookf (lua_State
*L
, lua_Debug
*ar
) {
207 static const char *const hooknames
[] =
208 {"call", "return", "line", "count", "tail return"};
209 lua_pushlightuserdata(L
, (void *)&KEY_HOOK
);
210 lua_rawget(L
, LUA_REGISTRYINDEX
);
211 lua_pushlightuserdata(L
, L
);
213 if (lua_isfunction(L
, -1)) {
214 lua_pushstring(L
, hooknames
[(int)ar
->event
]);
215 if (ar
->currentline
>= 0)
216 lua_pushinteger(L
, ar
->currentline
);
218 lua_assert(lua_getinfo(L
, "lS", ar
));
224 static int makemask (const char *smask
, int count
) {
226 if (strchr(smask
, 'c')) mask
|= LUA_MASKCALL
;
227 if (strchr(smask
, 'r')) mask
|= LUA_MASKRET
;
228 if (strchr(smask
, 'l')) mask
|= LUA_MASKLINE
;
229 if (count
> 0) mask
|= LUA_MASKCOUNT
;
234 static char *unmakemask (int mask
, char *smask
) {
236 if (mask
& LUA_MASKCALL
) smask
[i
++] = 'c';
237 if (mask
& LUA_MASKRET
) smask
[i
++] = 'r';
238 if (mask
& LUA_MASKLINE
) smask
[i
++] = 'l';
244 static void gethooktable (lua_State
*L
) {
245 lua_pushlightuserdata(L
, (void *)&KEY_HOOK
);
246 lua_rawget(L
, LUA_REGISTRYINDEX
);
247 if (!lua_istable(L
, -1)) {
249 lua_createtable(L
, 0, 1);
250 lua_pushlightuserdata(L
, (void *)&KEY_HOOK
);
251 lua_pushvalue(L
, -2);
252 lua_rawset(L
, LUA_REGISTRYINDEX
);
257 static int db_sethook (lua_State
*L
) {
258 int arg
, mask
, count
;
260 lua_State
*L1
= getthread(L
, &arg
);
261 if (lua_isnoneornil(L
, arg
+1)) {
262 lua_settop(L
, arg
+1);
263 func
= NULL
; mask
= 0; count
= 0; /* turn off hooks */
266 const char *smask
= luaL_checkstring(L
, arg
+2);
267 luaL_checktype(L
, arg
+1, LUA_TFUNCTION
);
268 count
= luaL_optint(L
, arg
+3, 0);
269 func
= hookf
; mask
= makemask(smask
, count
);
272 lua_pushlightuserdata(L
, L1
);
273 lua_pushvalue(L
, arg
+1);
274 lua_rawset(L
, -3); /* set new hook */
275 lua_pop(L
, 1); /* remove hook table */
276 lua_sethook(L1
, func
, mask
, count
); /* set hooks */
281 static int db_gethook (lua_State
*L
) {
283 lua_State
*L1
= getthread(L
, &arg
);
285 int mask
= lua_gethookmask(L1
);
286 lua_Hook hook
= lua_gethook(L1
);
287 if (hook
!= NULL
&& hook
!= hookf
) /* external hook? */
288 lua_pushliteral(L
, "external hook");
291 lua_pushlightuserdata(L
, L1
);
292 lua_rawget(L
, -2); /* get hook */
293 lua_remove(L
, -2); /* remove hook table */
295 lua_pushstring(L
, unmakemask(mask
, buff
));
296 lua_pushinteger(L
, lua_gethookcount(L1
));
301 static int db_debug (lua_State
*L
) {
304 fputs("lua_debug> ", stderr
);
305 if (fgets(buffer
, sizeof(buffer
), stdin
) == 0 ||
306 strcmp(buffer
, "cont\n") == 0)
308 if (luaL_loadbuffer(L
, buffer
, strlen(buffer
), "=(debug command)") ||
309 lua_pcall(L
, 0, 0, 0)) {
310 fputs(lua_tostring(L
, -1), stderr
);
313 lua_settop(L
, 0); /* remove eventual returns */
318 #define LEVELS1 12 /* size of the first part of the stack */
319 #define LEVELS2 10 /* size of the second part of the stack */
321 static int db_errorfb (lua_State
*L
) {
323 int firstpart
= 1; /* still before eventual `...' */
325 lua_State
*L1
= getthread(L
, &arg
);
327 if (lua_isnumber(L
, arg
+2)) {
328 level
= (int)lua_tointeger(L
, arg
+2);
332 level
= (L
== L1
) ? 1 : 0; /* level 0 may be this own function */
333 if (lua_gettop(L
) == arg
)
334 lua_pushliteral(L
, "");
335 else if (!lua_isstring(L
, arg
+1)) return 1; /* message is not a string */
336 else lua_pushliteral(L
, "\n");
337 lua_pushliteral(L
, "stack traceback:");
338 while (lua_getstack(L1
, level
++, &ar
)) {
339 if (level
> LEVELS1
&& firstpart
) {
340 /* no more than `LEVELS2' more levels? */
341 if (!lua_getstack(L1
, level
+LEVELS2
, &ar
))
342 level
--; /* keep going */
344 lua_pushliteral(L
, "\n\t..."); /* too many levels */
345 while (lua_getstack(L1
, level
+LEVELS2
, &ar
)) /* find last levels */
351 lua_pushliteral(L
, "\n\t");
352 lua_getinfo(L1
, "Snl", &ar
);
353 lua_pushfstring(L
, "%s:", ar
.short_src
);
354 if (ar
.currentline
> 0)
355 lua_pushfstring(L
, "%d:", ar
.currentline
);
356 if (*ar
.namewhat
!= '\0') /* is there a name? */
357 lua_pushfstring(L
, " in function " LUA_QS
, ar
.name
);
359 if (*ar
.what
== 'm') /* main? */
360 lua_pushfstring(L
, " in main chunk");
361 else if (*ar
.what
== 'C' || *ar
.what
== 't')
362 lua_pushliteral(L
, " ?"); /* C function or tail call */
364 lua_pushfstring(L
, " in function <%s:%d>",
365 ar
.short_src
, ar
.linedefined
);
367 lua_concat(L
, lua_gettop(L
) - arg
);
369 lua_concat(L
, lua_gettop(L
) - arg
);
374 static const luaL_Reg dblib
[] = {
376 {"getfenv", db_getfenv
},
377 {"gethook", db_gethook
},
378 {"getinfo", db_getinfo
},
379 {"getlocal", db_getlocal
},
380 {"getregistry", db_getregistry
},
381 {"getmetatable", db_getmetatable
},
382 {"getupvalue", db_getupvalue
},
383 {"setfenv", db_setfenv
},
384 {"sethook", db_sethook
},
385 {"setlocal", db_setlocal
},
386 {"setmetatable", db_setmetatable
},
387 {"setupvalue", db_setupvalue
},
388 {"traceback", db_errorfb
},
393 LUALIB_API
int luaopen_debug (lua_State
*L
) {
394 luaL_register(L
, LUA_DBLIBNAME
, dblib
);