commit 39b2d58c39fd0cd554b27ed071926bc439338964
parent d2d24f09713cfecf59a7688c45a3863a35f09254
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 8 Jul 2002 15:21:11 -0300
new interface for debug hooks
Diffstat:
M | ldblib.c | | | 89 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
M | ldebug.c | | | 41 | +++++++++++++++++++++++++---------------- |
M | ldebug.h | | | 9 | ++++++++- |
M | ldo.c | | | 67 | ++++++++++++++++++++++++++++--------------------------------------- |
M | ldo.h | | | 4 | ++-- |
M | lgc.c | | | 8 | ++++---- |
M | lstate.c | | | 9 | +++++---- |
M | lstate.h | | | 8 | ++++---- |
M | luadebug.h | | | 21 | +++++++++++++++++---- |
M | lvm.c | | | 38 | +++++++++++++++++++++++++------------- |
10 files changed, 165 insertions(+), 129 deletions(-)
diff --git a/ldblib.c b/ldblib.c
@@ -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 */
-}
-
-
-static int setcallhook (lua_State *L) {
- sethook(L, (void *)&KEY_CALLHOOK, callf, lua_setcallhook);
- return 1;
+ lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */
+ return 0;
}
-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},
diff --git a/ldebug.c b/ldebug.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.c,v 1.122 2002/06/20 20:39:44 roberto Exp roberto $
+** $Id: ldebug.c,v 1.123 2002/06/24 15:07:21 roberto Exp roberto $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -53,26 +53,31 @@ static int currentline (lua_State *L, CallInfo *ci) {
}
-LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) {
- lua_Hook oldhook;
- lua_lock(L);
- oldhook = L->callhook;
- L->callhook = func;
- lua_unlock(L);
- return oldhook;
-}
-
-
-LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) {
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) {
CallInfo *ci;
- lua_Hook oldhook;
+ int allow;
lua_lock(L);
- oldhook = L->linehook;
- L->linehook = func;
+ allow = allowhook(L);
+ if (func == NULL) mask = 0;
+ else if (mask == 0) func = NULL;
+ L->hook = func;
+ L->hookmask = mask;
+ setallowhook(L, allow);
+ resethookcount(L);
for (ci = L->base_ci; ci <= L->ci; ci++)
currentpc(L, ci); /* update `savedpc' */
lua_unlock(L);
- return oldhook;
+ return 1;
+}
+
+
+LUA_API lua_Hook lua_gethook (lua_State *L) {
+ return L->hook;
+}
+
+
+LUA_API int lua_gethookmask (lua_State *L) {
+ return L->hookmask;
}
@@ -396,6 +401,10 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
return pt->code[last];
}
+#undef check
+#undef checkjump
+#undef checkreg
+
/* }====================================================== */
diff --git a/ldebug.h b/ldebug.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.h,v 1.22 2002/06/18 15:19:27 roberto Exp roberto $
+** $Id: ldebug.h,v 1.23 2002/06/24 15:07:21 roberto Exp roberto $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -16,6 +16,13 @@
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
+#define resethookcount(L) \
+ (L->hookcount = (1 << lua_getmaskcount(L->hookmask)) >> 1)
+
+#define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond))
+#define allowhook(L) ((L->hookmask) & 1)
+
+
void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2);
diff --git a/ldo.c b/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 1.184 2002/06/26 16:37:23 roberto Exp roberto $
+** $Id: ldo.c,v 1.185 2002/07/04 12:29:32 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -135,40 +135,29 @@ static void luaD_openstack (lua_State *L, StkId pos) {
}
-static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) {
- ptrdiff_t top = savestack(L, L->top);
- ptrdiff_t ci_top = savestack(L, L->ci->top);
- ar->i_ci = L->ci - L->base_ci;
- luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
- L->ci->top = L->top + LUA_MINSTACK;
- L->allowhooks = 0; /* cannot call hooks inside a hook */
- lua_unlock(L);
- (*hook)(L, ar);
- lua_lock(L);
- lua_assert(L->allowhooks == 0);
- L->allowhooks = 1;
- L->ci->top = restorestack(L, ci_top);
- L->top = restorestack(L, top);
-}
-
-
-void luaD_lineHook (lua_State *L, int line) {
- if (L->allowhooks) {
- lua_Debug ar;
- ar.event = "line";
- ar.currentline = line;
- dohook(L, &ar, L->linehook);
- }
-}
-
-
-static void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) {
- if (L->allowhooks) {
+void luaD_callhook (lua_State *L, lua_Hookevent event, int line) {
+ lua_Hook hook = L->hook;
+ if (hook && allowhook(L)) {
+ ptrdiff_t top = savestack(L, L->top);
+ ptrdiff_t ci_top = savestack(L, L->ci->top);
lua_Debug ar;
ar.event = event;
- L->ci->pc = NULL; /* function is not active */
- L->ci->top = L->ci->base; /* `top' may not have a valid value yet */
- dohook(L, &ar, callhook);
+ ar.currentline = line;
+ ar.i_ci = L->ci - L->base_ci;
+ if (event <= LUA_HOOKRET) { /* `call' or `return' event? */
+ L->ci->pc = NULL; /* function is not active */
+ L->ci->top = L->ci->base; /* `top' may not have a valid value yet */
+ }
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ L->ci->top = L->top + LUA_MINSTACK;
+ setallowhook(L, 0); /* cannot call hooks inside a hook */
+ lua_unlock(L);
+ (*hook)(L, &ar);
+ lua_lock(L);
+ lua_assert(!allowhook(L));
+ setallowhook(L, 1);
+ L->ci->top = restorestack(L, ci_top);
+ L->top = restorestack(L, top);
}
}
@@ -219,8 +208,8 @@ StkId luaD_precall (lua_State *L, StkId func) {
if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */
func = tryfuncTM(L, func); /* check the `function' tag method */
cl = &clvalue(func)->l;
- if (L->callhook) {
- luaD_callHook(L, L->callhook, "call");
+ if (L->hookmask & LUA_MASKCALL) {
+ luaD_callhook(L, LUA_HOOKCALL, -1);
ci = L->ci; /* previous call may realocate `ci' */
}
if (!cl->isC) { /* Lua function? prepare its call */
@@ -252,9 +241,9 @@ StkId luaD_precall (lua_State *L, StkId func) {
void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
StkId res;
- if (L->callhook) {
+ if (L->hookmask & LUA_MASKRET) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
- luaD_callHook(L, L->callhook, "return");
+ luaD_callhook(L, LUA_HOOKRET, -1);
firstResult = restorestack(L, fr);
}
res = L->ci->base - 1; /* res == final position of 1st result */
@@ -483,7 +472,7 @@ int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
struct lua_longjmp lj;
lj.ci = L->ci;
lj.top = L->top;
- lj.allowhooks = L->allowhooks;
+ lj.allowhooks = allowhook(L);
lj.status = 0;
lj.err = ud;
lj.previous = L->errorJmp; /* chain new error handler */
@@ -493,7 +482,7 @@ int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
else { /* an error occurred */
L->ci = lj.ci; /* restore the state */
L->top = lj.top;
- L->allowhooks = lj.allowhooks;
+ setallowhook(L, lj.allowhooks);
restore_stack_limit(L);
}
L->errorJmp = lj.previous; /* restore old error handler */
diff --git a/ldo.h b/ldo.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.h,v 1.46 2002/06/18 15:19:27 roberto Exp roberto $
+** $Id: ldo.h,v 1.47 2002/06/18 17:10:43 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -32,7 +32,7 @@
typedef void (*Pfunc) (lua_State *L, void *v);
int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
-void luaD_lineHook (lua_State *L, int line);
+void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
StkId luaD_precall (lua_State *L, StkId func);
void luaD_call (lua_State *L, StkId func, int nResults);
int luaD_pcall (lua_State *L, int nargs, int nresults);
diff --git a/lgc.c b/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 1.140 2002/07/01 17:06:58 roberto Exp roberto $
+** $Id: lgc.c,v 1.141 2002/07/04 17:57:42 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -451,8 +451,8 @@ static void do1gcTM (lua_State *L, Udata *udata) {
static void callGCTM (lua_State *L) {
- int oldah = L->allowhooks;
- L->allowhooks = 0; /* stop debug hooks during GC tag methods */
+ int oldah = allowhook(L);
+ setallowhook(L, 0); /* stop debug hooks during GC tag methods */
L->top++; /* reserve space to keep udata while runs its gc method */
while (G(L)->tmudata != NULL) {
Udata *udata = G(L)->tmudata;
@@ -465,7 +465,7 @@ static void callGCTM (lua_State *L) {
do1gcTM(L, udata);
}
L->top--;
- L->allowhooks = oldah; /* restore hooks */
+ setallowhook(L, oldah); /* restore hooks */
}
diff --git a/lstate.c b/lstate.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.c,v 1.96 2002/06/06 18:17:33 roberto Exp roberto $
+** $Id: lstate.c,v 1.97 2002/06/18 15:19:27 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -92,12 +92,13 @@ static void preinit_state (lua_State *L) {
L->stack = NULL;
L->stacksize = 0;
L->errorJmp = NULL;
- L->callhook = NULL;
- L->linehook = NULL;
+ L->hook = NULL;
+ L->hookmask = 0;
+ setallowhook(L, 1);
+ resethookcount(L);
L->openupval = NULL;
L->size_ci = 0;
L->base_ci = NULL;
- L->allowhooks = 1;
}
diff --git a/lstate.h b/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 1.85 2002/05/08 17:34:23 roberto Exp roberto $
+** $Id: lstate.h,v 1.86 2002/07/02 16:43:28 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -130,8 +130,9 @@ struct lua_State {
CallInfo *end_ci; /* points after end of ci array*/
CallInfo *base_ci; /* array of CallInfo's */
global_State *l_G;
- lua_Hook linehook;
- lua_Hook callhook;
+ int hookmask;
+ int hookcount;
+ lua_Hook hook;
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
struct lua_longjmp *errorJmp; /* current error recover point */
UpVal *openupval; /* list of open upvalues in this stack */
@@ -139,7 +140,6 @@ struct lua_State {
lua_State *previous;
int stacksize;
int size_ci; /* size of array `base_ci' */
- int allowhooks;
};
diff --git a/luadebug.h b/luadebug.h
@@ -1,5 +1,5 @@
/*
-** $Id: luadebug.h,v 1.27 2002/04/04 17:21:31 roberto Exp roberto $
+** $Id: luadebug.h,v 1.28 2002/06/18 17:10:43 roberto Exp roberto $
** Debugging API
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,18 @@
#include "lua.h"
+typedef enum lua_Hookevent {
+ LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKLINE, LUA_HOOKCOUNT
+} lua_Hookevent;
+
+
+#define LUA_MASKCALL (2 << LUA_HOOKCALL)
+#define LUA_MASKRET (2 << LUA_HOOKRET)
+#define LUA_MASKLINE (2 << LUA_HOOKLINE)
+#define lua_maskcount(count) ((count) << (LUA_HOOKCOUNT+1))
+#define lua_getmaskcount(mask) ((mask) >> (LUA_HOOKCOUNT+1))
+#define LUA_MASKCOUNT (lua_maskcount(1))
+
typedef struct lua_Debug lua_Debug; /* activation record */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
@@ -21,14 +33,15 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
-LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func);
-LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func);
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask);
+LUA_API lua_Hook lua_gethook (lua_State *L);
+LUA_API int lua_gethookmask (lua_State *L);
#define LUA_IDSIZE 60
struct lua_Debug {
- const char *event; /* `call', `return', `line' */
+ lua_Hookevent event;
const char *name; /* (n) */
const char *namewhat; /* (n) `global', `local', `field', `method' */
const char *what; /* (S) `Lua' function, `C' function, Lua `main' */
diff --git a/lvm.c b/lvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.c,v 1.243 2002/06/24 15:07:21 roberto Exp roberto $
+** $Id: lvm.c,v 1.244 2002/07/05 18:27:39 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -69,17 +69,28 @@ int luaV_tostring (lua_State *L, TObject *obj) {
static void traceexec (lua_State *L) {
- CallInfo *ci = L->ci;
- Proto *p = ci_func(ci)->l.p;
- int newline = getline(p, pcRel(*ci->pc, p));
- if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */
- ci->savedpc = *ci->pc; /* initialize `savedpc' */
- /* calls linehook when enters a new line or jumps back (loop) */
- if (*ci->pc <= ci->savedpc || newline != getline(p, pcRel(ci->savedpc, p))) {
- luaD_lineHook(L, newline);
- ci = L->ci; /* previous call may reallocate `ci' */
+ int mask = L->hookmask;
+ if (mask >= LUA_MASKCOUNT) { /* instruction hook set? */
+ if (L->hookcount == 0) {
+ luaD_callhook(L, LUA_HOOKCOUNT, -1);
+ resethookcount(L);
+ return;
+ }
+ }
+ if (mask & LUA_MASKLINE) {
+ CallInfo *ci = L->ci;
+ Proto *p = ci_func(ci)->l.p;
+ int newline = getline(p, pcRel(*ci->pc, p));
+ if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */
+ ci->savedpc = *ci->pc; /* initialize `savedpc' */
+ /* calls linehook when enters a new line or jumps back (loop) */
+ if (*ci->pc <= ci->savedpc ||
+ newline != getline(p, pcRel(ci->savedpc, p))) {
+ luaD_callhook(L, LUA_HOOKLINE, newline);
+ ci = L->ci; /* previous call may reallocate `ci' */
+ }
+ ci->savedpc = *ci->pc;
}
- ci->savedpc = *ci->pc;
}
@@ -370,8 +381,9 @@ StkId luaV_execute (lua_State *L) {
for (;;) {
const Instruction i = *pc++;
StkId ra;
- if (L->linehook)
- traceexec(L);
+ if (L->hookmask >= LUA_MASKLINE &&
+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
+ traceexec(L);
ra = RA(i);
lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
lua_assert(L->top == L->ci->top ||