new interface for debug hooks

This commit is contained in:
Roberto Ierusalimschy
2002-07-08 15:21:33 -03:00
parent d2d24f0971
commit 39b2d58c39
10 changed files with 165 additions and 129 deletions

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldblib.c,v 1.60 2002/06/18 17:42:52 roberto Exp roberto $
** $Id: ldblib.c,v 1.61 2002/06/25 19:16:44 roberto Exp roberto $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -108,65 +108,70 @@ static int setlocal (lua_State *L) {
static const char KEY_CALLHOOK = 'c';
static const char KEY_LINEHOOK = 'l';
static const char KEY_HOOK = 'h';
static void hookf (lua_State *L, void *key) {
lua_pushudataval(L, key);
static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] = {"call", "return", "line", "count"};
lua_pushudataval(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isfunction(L, -1)) {
lua_pushvalue(L, -2); /* original argument (below function) */
lua_call(L, 1, 0);
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0) lua_pushnumber(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
else
lua_pop(L, 1); /* pop result from gettable */
}
static void callf (lua_State *L, lua_Debug *ar) {
lua_pushstring(L, ar->event);
lua_assert(lua_getinfo(L, "lS", ar) && ar->currentline == -1);
hookf(L, (void *)&KEY_CALLHOOK);
static int makemask (const char *smask, int count) {
int mask = 0;
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
return mask | lua_maskcount(count);
}
static void linef (lua_State *L, lua_Debug *ar) {
lua_pushnumber(L, ar->currentline);
lua_assert((ar->currentline = ar->linedefined = -1,
lua_getinfo(L, "lS", ar) &&
ar->currentline == lua_tonumber(L, -1) &&
ar->linedefined >= 0));
hookf(L, (void *)&KEY_LINEHOOK);
static char *unmakemask (int mask, char *smask) {
int i = 0;
if (mask & LUA_MASKCALL) smask[i++] = 'c';
if (mask & LUA_MASKRET) smask[i++] = 'r';
if (mask & LUA_MASKLINE) smask[i++] = 'l';
smask[i] = '\0';
return smask;
}
static void sethook (lua_State *L, void *key, lua_Hook hook,
lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) {
lua_settop(L, 1);
if (lua_isnoneornil(L, 1))
(*sethookf)(L, NULL);
else if (lua_isfunction(L, 1))
(*sethookf)(L, hook);
else
luaL_argerror(L, 1, "function expected");
lua_pushudataval(L, key);
lua_rawget(L, LUA_REGISTRYINDEX); /* get old value */
lua_pushudataval(L, key);
static int sethook (lua_State *L) {
if (lua_isnoneornil(L, 1)) {
lua_settop(L, 1);
lua_sethook(L, NULL, 0); /* turn off hooks */
}
else {
const char *smask = luaL_check_string(L, 2);
int count = luaL_opt_int(L, 3, 0);
luaL_check_type(L, 1, LUA_TFUNCTION);
lua_sethook(L, hookf, makemask(smask, count));
}
lua_pushudataval(L, (void *)&KEY_HOOK);
lua_pushvalue(L, 1);
lua_rawset(L, LUA_REGISTRYINDEX); /* set new value */
lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */
return 0;
}
static int setcallhook (lua_State *L) {
sethook(L, (void *)&KEY_CALLHOOK, callf, lua_setcallhook);
return 1;
}
static int setlinehook (lua_State *L) {
sethook(L, (void *)&KEY_LINEHOOK, linef, lua_setlinehook);
return 1;
static int gethook (lua_State *L) {
char buff[5];
int mask = lua_gethookmask(L);
lua_pushudataval(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
lua_pushstring(L, unmakemask(mask, buff));
lua_pushnumber(L, lua_getmaskcount(mask));
return 3;
}
@@ -245,8 +250,8 @@ static int errorfb (lua_State *L) {
static const luaL_reg dblib[] = {
{"getlocal", getlocal},
{"getinfo", getinfo},
{"setcallhook", setcallhook},
{"setlinehook", setlinehook},
{"gethook", gethook},
{"sethook", sethook},
{"setlocal", setlocal},
{"debug", debug},
{"traceback", errorfb},