diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-07-08 15:21:33 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-07-08 15:21:33 -0300 |
| commit | 39b2d58c39fd0cd554b27ed071926bc439338964 (patch) | |
| tree | 6855ede1b0e908439476e54396f94ae9ad275269 | |
| parent | d2d24f09713cfecf59a7688c45a3863a35f09254 (diff) | |
| download | lua-39b2d58c39fd0cd554b27ed071926bc439338964.tar.gz lua-39b2d58c39fd0cd554b27ed071926bc439338964.tar.bz2 lua-39b2d58c39fd0cd554b27ed071926bc439338964.zip | |
new interface for debug hooks
| -rw-r--r-- | ldblib.c | 89 | ||||
| -rw-r--r-- | ldebug.c | 41 | ||||
| -rw-r--r-- | ldebug.h | 9 | ||||
| -rw-r--r-- | ldo.c | 67 | ||||
| -rw-r--r-- | ldo.h | 4 | ||||
| -rw-r--r-- | lgc.c | 8 | ||||
| -rw-r--r-- | lstate.c | 9 | ||||
| -rw-r--r-- | lstate.h | 8 | ||||
| -rw-r--r-- | luadebug.h | 21 | ||||
| -rw-r--r-- | lvm.c | 38 |
10 files changed, 165 insertions, 129 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldblib.c,v 1.60 2002/06/18 17:42:52 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.61 2002/06/25 19:16:44 roberto Exp roberto $ |
| 3 | ** Interface from Lua to its debug API | 3 | ** Interface from Lua to its debug API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -108,65 +108,70 @@ static int setlocal (lua_State *L) { | |||
| 108 | 108 | ||
| 109 | 109 | ||
| 110 | 110 | ||
| 111 | static const char KEY_CALLHOOK = 'c'; | 111 | static const char KEY_HOOK = 'h'; |
| 112 | static const char KEY_LINEHOOK = 'l'; | ||
| 113 | 112 | ||
| 114 | 113 | ||
| 115 | static void hookf (lua_State *L, void *key) { | 114 | static void hookf (lua_State *L, lua_Debug *ar) { |
| 116 | lua_pushudataval(L, key); | 115 | static const char *const hooknames[] = {"call", "return", "line", "count"}; |
| 116 | lua_pushudataval(L, (void *)&KEY_HOOK); | ||
| 117 | lua_rawget(L, LUA_REGISTRYINDEX); | 117 | lua_rawget(L, LUA_REGISTRYINDEX); |
| 118 | if (lua_isfunction(L, -1)) { | 118 | if (lua_isfunction(L, -1)) { |
| 119 | lua_pushvalue(L, -2); /* original argument (below function) */ | 119 | lua_pushstring(L, hooknames[(int)ar->event]); |
| 120 | lua_call(L, 1, 0); | 120 | if (ar->currentline >= 0) lua_pushnumber(L, ar->currentline); |
| 121 | else lua_pushnil(L); | ||
| 122 | lua_assert(lua_getinfo(L, "lS", ar)); | ||
| 123 | lua_call(L, 2, 0); | ||
| 121 | } | 124 | } |
| 122 | else | 125 | else |
| 123 | lua_pop(L, 1); /* pop result from gettable */ | 126 | lua_pop(L, 1); /* pop result from gettable */ |
| 124 | } | 127 | } |
| 125 | 128 | ||
| 126 | 129 | ||
| 127 | static void callf (lua_State *L, lua_Debug *ar) { | 130 | static int makemask (const char *smask, int count) { |
| 128 | lua_pushstring(L, ar->event); | 131 | int mask = 0; |
| 129 | lua_assert(lua_getinfo(L, "lS", ar) && ar->currentline == -1); | 132 | if (strchr(smask, 'c')) mask |= LUA_MASKCALL; |
| 130 | hookf(L, (void *)&KEY_CALLHOOK); | 133 | if (strchr(smask, 'r')) mask |= LUA_MASKRET; |
| 134 | if (strchr(smask, 'l')) mask |= LUA_MASKLINE; | ||
| 135 | return mask | lua_maskcount(count); | ||
| 131 | } | 136 | } |
| 132 | 137 | ||
| 133 | 138 | ||
| 134 | static void linef (lua_State *L, lua_Debug *ar) { | 139 | static char *unmakemask (int mask, char *smask) { |
| 135 | lua_pushnumber(L, ar->currentline); | 140 | int i = 0; |
| 136 | lua_assert((ar->currentline = ar->linedefined = -1, | 141 | if (mask & LUA_MASKCALL) smask[i++] = 'c'; |
| 137 | lua_getinfo(L, "lS", ar) && | 142 | if (mask & LUA_MASKRET) smask[i++] = 'r'; |
| 138 | ar->currentline == lua_tonumber(L, -1) && | 143 | if (mask & LUA_MASKLINE) smask[i++] = 'l'; |
| 139 | ar->linedefined >= 0)); | 144 | smask[i] = '\0'; |
| 140 | hookf(L, (void *)&KEY_LINEHOOK); | 145 | return smask; |
| 141 | } | 146 | } |
| 142 | 147 | ||
| 143 | 148 | ||
| 144 | static void sethook (lua_State *L, void *key, lua_Hook hook, | 149 | static int sethook (lua_State *L) { |
| 145 | lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) { | 150 | if (lua_isnoneornil(L, 1)) { |
| 146 | lua_settop(L, 1); | 151 | lua_settop(L, 1); |
| 147 | if (lua_isnoneornil(L, 1)) | 152 | lua_sethook(L, NULL, 0); /* turn off hooks */ |
| 148 | (*sethookf)(L, NULL); | 153 | } |
| 149 | else if (lua_isfunction(L, 1)) | 154 | else { |
| 150 | (*sethookf)(L, hook); | 155 | const char *smask = luaL_check_string(L, 2); |
| 151 | else | 156 | int count = luaL_opt_int(L, 3, 0); |
| 152 | luaL_argerror(L, 1, "function expected"); | 157 | luaL_check_type(L, 1, LUA_TFUNCTION); |
| 153 | lua_pushudataval(L, key); | 158 | lua_sethook(L, hookf, makemask(smask, count)); |
| 154 | lua_rawget(L, LUA_REGISTRYINDEX); /* get old value */ | 159 | } |
| 155 | lua_pushudataval(L, key); | 160 | lua_pushudataval(L, (void *)&KEY_HOOK); |
| 156 | lua_pushvalue(L, 1); | 161 | lua_pushvalue(L, 1); |
| 157 | lua_rawset(L, LUA_REGISTRYINDEX); /* set new value */ | 162 | lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ |
| 158 | } | 163 | return 0; |
| 159 | |||
| 160 | |||
| 161 | static int setcallhook (lua_State *L) { | ||
| 162 | sethook(L, (void *)&KEY_CALLHOOK, callf, lua_setcallhook); | ||
| 163 | return 1; | ||
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | static int setlinehook (lua_State *L) { | 167 | static int gethook (lua_State *L) { |
| 168 | sethook(L, (void *)&KEY_LINEHOOK, linef, lua_setlinehook); | 168 | char buff[5]; |
| 169 | return 1; | 169 | int mask = lua_gethookmask(L); |
| 170 | lua_pushudataval(L, (void *)&KEY_HOOK); | ||
| 171 | lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ | ||
| 172 | lua_pushstring(L, unmakemask(mask, buff)); | ||
| 173 | lua_pushnumber(L, lua_getmaskcount(mask)); | ||
| 174 | return 3; | ||
| 170 | } | 175 | } |
| 171 | 176 | ||
| 172 | 177 | ||
| @@ -245,8 +250,8 @@ static int errorfb (lua_State *L) { | |||
| 245 | static const luaL_reg dblib[] = { | 250 | static const luaL_reg dblib[] = { |
| 246 | {"getlocal", getlocal}, | 251 | {"getlocal", getlocal}, |
| 247 | {"getinfo", getinfo}, | 252 | {"getinfo", getinfo}, |
| 248 | {"setcallhook", setcallhook}, | 253 | {"gethook", gethook}, |
| 249 | {"setlinehook", setlinehook}, | 254 | {"sethook", sethook}, |
| 250 | {"setlocal", setlocal}, | 255 | {"setlocal", setlocal}, |
| 251 | {"debug", debug}, | 256 | {"debug", debug}, |
| 252 | {"traceback", errorfb}, | 257 | {"traceback", errorfb}, |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 1.122 2002/06/20 20:39:44 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.123 2002/06/24 15:07:21 roberto Exp roberto $ |
| 3 | ** Debug Interface | 3 | ** Debug Interface |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -53,26 +53,31 @@ static int currentline (lua_State *L, CallInfo *ci) { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) { | 56 | LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) { |
| 57 | lua_Hook oldhook; | ||
| 58 | lua_lock(L); | ||
| 59 | oldhook = L->callhook; | ||
| 60 | L->callhook = func; | ||
| 61 | lua_unlock(L); | ||
| 62 | return oldhook; | ||
| 63 | } | ||
| 64 | |||
| 65 | |||
| 66 | LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) { | ||
| 67 | CallInfo *ci; | 57 | CallInfo *ci; |
| 68 | lua_Hook oldhook; | 58 | int allow; |
| 69 | lua_lock(L); | 59 | lua_lock(L); |
| 70 | oldhook = L->linehook; | 60 | allow = allowhook(L); |
| 71 | L->linehook = func; | 61 | if (func == NULL) mask = 0; |
| 62 | else if (mask == 0) func = NULL; | ||
| 63 | L->hook = func; | ||
| 64 | L->hookmask = mask; | ||
| 65 | setallowhook(L, allow); | ||
| 66 | resethookcount(L); | ||
| 72 | for (ci = L->base_ci; ci <= L->ci; ci++) | 67 | for (ci = L->base_ci; ci <= L->ci; ci++) |
| 73 | currentpc(L, ci); /* update `savedpc' */ | 68 | currentpc(L, ci); /* update `savedpc' */ |
| 74 | lua_unlock(L); | 69 | lua_unlock(L); |
| 75 | return oldhook; | 70 | return 1; |
| 71 | } | ||
| 72 | |||
| 73 | |||
| 74 | LUA_API lua_Hook lua_gethook (lua_State *L) { | ||
| 75 | return L->hook; | ||
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | LUA_API int lua_gethookmask (lua_State *L) { | ||
| 80 | return L->hookmask; | ||
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | 83 | ||
| @@ -396,6 +401,10 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
| 396 | return pt->code[last]; | 401 | return pt->code[last]; |
| 397 | } | 402 | } |
| 398 | 403 | ||
| 404 | #undef check | ||
| 405 | #undef checkjump | ||
| 406 | #undef checkreg | ||
| 407 | |||
| 399 | /* }====================================================== */ | 408 | /* }====================================================== */ |
| 400 | 409 | ||
| 401 | 410 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.h,v 1.22 2002/06/18 15:19:27 roberto Exp roberto $ | 2 | ** $Id: ldebug.h,v 1.23 2002/06/24 15:07:21 roberto Exp roberto $ |
| 3 | ** Auxiliary functions from Debug Interface module | 3 | ** Auxiliary functions from Debug Interface module |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -16,6 +16,13 @@ | |||
| 16 | 16 | ||
| 17 | #define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) | 17 | #define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) |
| 18 | 18 | ||
| 19 | #define resethookcount(L) \ | ||
| 20 | (L->hookcount = (1 << lua_getmaskcount(L->hookmask)) >> 1) | ||
| 21 | |||
| 22 | #define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond)) | ||
| 23 | #define allowhook(L) ((L->hookmask) & 1) | ||
| 24 | |||
| 25 | |||
| 19 | void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); | 26 | void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); |
| 20 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2); | 27 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2); |
| 21 | void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2); | 28 | void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.184 2002/06/26 16:37:23 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.185 2002/07/04 12:29:32 roberto Exp roberto $ |
| 3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -135,40 +135,29 @@ static void luaD_openstack (lua_State *L, StkId pos) { | |||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | 137 | ||
| 138 | static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { | 138 | void luaD_callhook (lua_State *L, lua_Hookevent event, int line) { |
| 139 | ptrdiff_t top = savestack(L, L->top); | 139 | lua_Hook hook = L->hook; |
| 140 | ptrdiff_t ci_top = savestack(L, L->ci->top); | 140 | if (hook && allowhook(L)) { |
| 141 | ar->i_ci = L->ci - L->base_ci; | 141 | ptrdiff_t top = savestack(L, L->top); |
| 142 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 142 | ptrdiff_t ci_top = savestack(L, L->ci->top); |
| 143 | L->ci->top = L->top + LUA_MINSTACK; | ||
| 144 | L->allowhooks = 0; /* cannot call hooks inside a hook */ | ||
| 145 | lua_unlock(L); | ||
| 146 | (*hook)(L, ar); | ||
| 147 | lua_lock(L); | ||
| 148 | lua_assert(L->allowhooks == 0); | ||
| 149 | L->allowhooks = 1; | ||
| 150 | L->ci->top = restorestack(L, ci_top); | ||
| 151 | L->top = restorestack(L, top); | ||
| 152 | } | ||
| 153 | |||
| 154 | |||
| 155 | void luaD_lineHook (lua_State *L, int line) { | ||
| 156 | if (L->allowhooks) { | ||
| 157 | lua_Debug ar; | ||
| 158 | ar.event = "line"; | ||
| 159 | ar.currentline = line; | ||
| 160 | dohook(L, &ar, L->linehook); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | |||
| 165 | static void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) { | ||
| 166 | if (L->allowhooks) { | ||
| 167 | lua_Debug ar; | 143 | lua_Debug ar; |
| 168 | ar.event = event; | 144 | ar.event = event; |
| 169 | L->ci->pc = NULL; /* function is not active */ | 145 | ar.currentline = line; |
| 170 | L->ci->top = L->ci->base; /* `top' may not have a valid value yet */ | 146 | ar.i_ci = L->ci - L->base_ci; |
| 171 | dohook(L, &ar, callhook); | 147 | if (event <= LUA_HOOKRET) { /* `call' or `return' event? */ |
| 148 | L->ci->pc = NULL; /* function is not active */ | ||
| 149 | L->ci->top = L->ci->base; /* `top' may not have a valid value yet */ | ||
| 150 | } | ||
| 151 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | ||
| 152 | L->ci->top = L->top + LUA_MINSTACK; | ||
| 153 | setallowhook(L, 0); /* cannot call hooks inside a hook */ | ||
| 154 | lua_unlock(L); | ||
| 155 | (*hook)(L, &ar); | ||
| 156 | lua_lock(L); | ||
| 157 | lua_assert(!allowhook(L)); | ||
| 158 | setallowhook(L, 1); | ||
| 159 | L->ci->top = restorestack(L, ci_top); | ||
| 160 | L->top = restorestack(L, top); | ||
| 172 | } | 161 | } |
| 173 | } | 162 | } |
| 174 | 163 | ||
| @@ -219,8 +208,8 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 219 | if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */ | 208 | if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */ |
| 220 | func = tryfuncTM(L, func); /* check the `function' tag method */ | 209 | func = tryfuncTM(L, func); /* check the `function' tag method */ |
| 221 | cl = &clvalue(func)->l; | 210 | cl = &clvalue(func)->l; |
| 222 | if (L->callhook) { | 211 | if (L->hookmask & LUA_MASKCALL) { |
| 223 | luaD_callHook(L, L->callhook, "call"); | 212 | luaD_callhook(L, LUA_HOOKCALL, -1); |
| 224 | ci = L->ci; /* previous call may realocate `ci' */ | 213 | ci = L->ci; /* previous call may realocate `ci' */ |
| 225 | } | 214 | } |
| 226 | if (!cl->isC) { /* Lua function? prepare its call */ | 215 | if (!cl->isC) { /* Lua function? prepare its call */ |
| @@ -252,9 +241,9 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 252 | 241 | ||
| 253 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | 242 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { |
| 254 | StkId res; | 243 | StkId res; |
| 255 | if (L->callhook) { | 244 | if (L->hookmask & LUA_MASKRET) { |
| 256 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | 245 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ |
| 257 | luaD_callHook(L, L->callhook, "return"); | 246 | luaD_callhook(L, LUA_HOOKRET, -1); |
| 258 | firstResult = restorestack(L, fr); | 247 | firstResult = restorestack(L, fr); |
| 259 | } | 248 | } |
| 260 | res = L->ci->base - 1; /* res == final position of 1st result */ | 249 | 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) { | |||
| 483 | struct lua_longjmp lj; | 472 | struct lua_longjmp lj; |
| 484 | lj.ci = L->ci; | 473 | lj.ci = L->ci; |
| 485 | lj.top = L->top; | 474 | lj.top = L->top; |
| 486 | lj.allowhooks = L->allowhooks; | 475 | lj.allowhooks = allowhook(L); |
| 487 | lj.status = 0; | 476 | lj.status = 0; |
| 488 | lj.err = ud; | 477 | lj.err = ud; |
| 489 | lj.previous = L->errorJmp; /* chain new error handler */ | 478 | lj.previous = L->errorJmp; /* chain new error handler */ |
| @@ -493,7 +482,7 @@ int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) { | |||
| 493 | else { /* an error occurred */ | 482 | else { /* an error occurred */ |
| 494 | L->ci = lj.ci; /* restore the state */ | 483 | L->ci = lj.ci; /* restore the state */ |
| 495 | L->top = lj.top; | 484 | L->top = lj.top; |
| 496 | L->allowhooks = lj.allowhooks; | 485 | setallowhook(L, lj.allowhooks); |
| 497 | restore_stack_limit(L); | 486 | restore_stack_limit(L); |
| 498 | } | 487 | } |
| 499 | L->errorJmp = lj.previous; /* restore old error handler */ | 488 | L->errorJmp = lj.previous; /* restore old error handler */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 1.46 2002/06/18 15:19:27 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 1.47 2002/06/18 17:10:43 roberto Exp roberto $ |
| 3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -32,7 +32,7 @@ | |||
| 32 | typedef void (*Pfunc) (lua_State *L, void *v); | 32 | typedef void (*Pfunc) (lua_State *L, void *v); |
| 33 | 33 | ||
| 34 | int luaD_protectedparser (lua_State *L, ZIO *z, int bin); | 34 | int luaD_protectedparser (lua_State *L, ZIO *z, int bin); |
| 35 | void luaD_lineHook (lua_State *L, int line); | 35 | void luaD_callhook (lua_State *L, lua_Hookevent event, int line); |
| 36 | StkId luaD_precall (lua_State *L, StkId func); | 36 | StkId luaD_precall (lua_State *L, StkId func); |
| 37 | void luaD_call (lua_State *L, StkId func, int nResults); | 37 | void luaD_call (lua_State *L, StkId func, int nResults); |
| 38 | int luaD_pcall (lua_State *L, int nargs, int nresults); | 38 | int luaD_pcall (lua_State *L, int nargs, int nresults); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 1.140 2002/07/01 17:06:58 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.141 2002/07/04 17:57:42 roberto Exp $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -451,8 +451,8 @@ static void do1gcTM (lua_State *L, Udata *udata) { | |||
| 451 | 451 | ||
| 452 | 452 | ||
| 453 | static void callGCTM (lua_State *L) { | 453 | static void callGCTM (lua_State *L) { |
| 454 | int oldah = L->allowhooks; | 454 | int oldah = allowhook(L); |
| 455 | L->allowhooks = 0; /* stop debug hooks during GC tag methods */ | 455 | setallowhook(L, 0); /* stop debug hooks during GC tag methods */ |
| 456 | L->top++; /* reserve space to keep udata while runs its gc method */ | 456 | L->top++; /* reserve space to keep udata while runs its gc method */ |
| 457 | while (G(L)->tmudata != NULL) { | 457 | while (G(L)->tmudata != NULL) { |
| 458 | Udata *udata = G(L)->tmudata; | 458 | Udata *udata = G(L)->tmudata; |
| @@ -465,7 +465,7 @@ static void callGCTM (lua_State *L) { | |||
| 465 | do1gcTM(L, udata); | 465 | do1gcTM(L, udata); |
| 466 | } | 466 | } |
| 467 | L->top--; | 467 | L->top--; |
| 468 | L->allowhooks = oldah; /* restore hooks */ | 468 | setallowhook(L, oldah); /* restore hooks */ |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | 471 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 1.96 2002/06/06 18:17:33 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.97 2002/06/18 15:19:27 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -92,12 +92,13 @@ static void preinit_state (lua_State *L) { | |||
| 92 | L->stack = NULL; | 92 | L->stack = NULL; |
| 93 | L->stacksize = 0; | 93 | L->stacksize = 0; |
| 94 | L->errorJmp = NULL; | 94 | L->errorJmp = NULL; |
| 95 | L->callhook = NULL; | 95 | L->hook = NULL; |
| 96 | L->linehook = NULL; | 96 | L->hookmask = 0; |
| 97 | setallowhook(L, 1); | ||
| 98 | resethookcount(L); | ||
| 97 | L->openupval = NULL; | 99 | L->openupval = NULL; |
| 98 | L->size_ci = 0; | 100 | L->size_ci = 0; |
| 99 | L->base_ci = NULL; | 101 | L->base_ci = NULL; |
| 100 | L->allowhooks = 1; | ||
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | 104 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 1.85 2002/05/08 17:34:23 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.86 2002/07/02 16:43:28 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -130,8 +130,9 @@ struct lua_State { | |||
| 130 | CallInfo *end_ci; /* points after end of ci array*/ | 130 | CallInfo *end_ci; /* points after end of ci array*/ |
| 131 | CallInfo *base_ci; /* array of CallInfo's */ | 131 | CallInfo *base_ci; /* array of CallInfo's */ |
| 132 | global_State *l_G; | 132 | global_State *l_G; |
| 133 | lua_Hook linehook; | 133 | int hookmask; |
| 134 | lua_Hook callhook; | 134 | int hookcount; |
| 135 | lua_Hook hook; | ||
| 135 | TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */ | 136 | TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */ |
| 136 | struct lua_longjmp *errorJmp; /* current error recover point */ | 137 | struct lua_longjmp *errorJmp; /* current error recover point */ |
| 137 | UpVal *openupval; /* list of open upvalues in this stack */ | 138 | UpVal *openupval; /* list of open upvalues in this stack */ |
| @@ -139,7 +140,6 @@ struct lua_State { | |||
| 139 | lua_State *previous; | 140 | lua_State *previous; |
| 140 | int stacksize; | 141 | int stacksize; |
| 141 | int size_ci; /* size of array `base_ci' */ | 142 | int size_ci; /* size of array `base_ci' */ |
| 142 | int allowhooks; | ||
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | 145 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: luadebug.h,v 1.27 2002/04/04 17:21:31 roberto Exp roberto $ | 2 | ** $Id: luadebug.h,v 1.28 2002/06/18 17:10:43 roberto Exp roberto $ |
| 3 | ** Debugging API | 3 | ** Debugging API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -11,6 +11,18 @@ | |||
| 11 | 11 | ||
| 12 | #include "lua.h" | 12 | #include "lua.h" |
| 13 | 13 | ||
| 14 | typedef enum lua_Hookevent { | ||
| 15 | LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKLINE, LUA_HOOKCOUNT | ||
| 16 | } lua_Hookevent; | ||
| 17 | |||
| 18 | |||
| 19 | #define LUA_MASKCALL (2 << LUA_HOOKCALL) | ||
| 20 | #define LUA_MASKRET (2 << LUA_HOOKRET) | ||
| 21 | #define LUA_MASKLINE (2 << LUA_HOOKLINE) | ||
| 22 | #define lua_maskcount(count) ((count) << (LUA_HOOKCOUNT+1)) | ||
| 23 | #define lua_getmaskcount(mask) ((mask) >> (LUA_HOOKCOUNT+1)) | ||
| 24 | #define LUA_MASKCOUNT (lua_maskcount(1)) | ||
| 25 | |||
| 14 | typedef struct lua_Debug lua_Debug; /* activation record */ | 26 | typedef struct lua_Debug lua_Debug; /* activation record */ |
| 15 | 27 | ||
| 16 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); | 28 | 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); | |||
| 21 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); | 33 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); |
| 22 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); | 34 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); |
| 23 | 35 | ||
| 24 | LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); | 36 | LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask); |
| 25 | LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func); | 37 | LUA_API lua_Hook lua_gethook (lua_State *L); |
| 38 | LUA_API int lua_gethookmask (lua_State *L); | ||
| 26 | 39 | ||
| 27 | 40 | ||
| 28 | #define LUA_IDSIZE 60 | 41 | #define LUA_IDSIZE 60 |
| 29 | 42 | ||
| 30 | struct lua_Debug { | 43 | struct lua_Debug { |
| 31 | const char *event; /* `call', `return', `line' */ | 44 | lua_Hookevent event; |
| 32 | const char *name; /* (n) */ | 45 | const char *name; /* (n) */ |
| 33 | const char *namewhat; /* (n) `global', `local', `field', `method' */ | 46 | const char *namewhat; /* (n) `global', `local', `field', `method' */ |
| 34 | const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ | 47 | const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.243 2002/06/24 15:07:21 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.244 2002/07/05 18:27:39 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -69,17 +69,28 @@ int luaV_tostring (lua_State *L, TObject *obj) { | |||
| 69 | 69 | ||
| 70 | 70 | ||
| 71 | static void traceexec (lua_State *L) { | 71 | static void traceexec (lua_State *L) { |
| 72 | CallInfo *ci = L->ci; | 72 | int mask = L->hookmask; |
| 73 | Proto *p = ci_func(ci)->l.p; | 73 | if (mask >= LUA_MASKCOUNT) { /* instruction hook set? */ |
| 74 | int newline = getline(p, pcRel(*ci->pc, p)); | 74 | if (L->hookcount == 0) { |
| 75 | if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */ | 75 | luaD_callhook(L, LUA_HOOKCOUNT, -1); |
| 76 | ci->savedpc = *ci->pc; /* initialize `savedpc' */ | 76 | resethookcount(L); |
| 77 | /* calls linehook when enters a new line or jumps back (loop) */ | 77 | return; |
| 78 | if (*ci->pc <= ci->savedpc || newline != getline(p, pcRel(ci->savedpc, p))) { | 78 | } |
| 79 | luaD_lineHook(L, newline); | 79 | } |
| 80 | ci = L->ci; /* previous call may reallocate `ci' */ | 80 | if (mask & LUA_MASKLINE) { |
| 81 | CallInfo *ci = L->ci; | ||
| 82 | Proto *p = ci_func(ci)->l.p; | ||
| 83 | int newline = getline(p, pcRel(*ci->pc, p)); | ||
| 84 | if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */ | ||
| 85 | ci->savedpc = *ci->pc; /* initialize `savedpc' */ | ||
| 86 | /* calls linehook when enters a new line or jumps back (loop) */ | ||
| 87 | if (*ci->pc <= ci->savedpc || | ||
| 88 | newline != getline(p, pcRel(ci->savedpc, p))) { | ||
| 89 | luaD_callhook(L, LUA_HOOKLINE, newline); | ||
| 90 | ci = L->ci; /* previous call may reallocate `ci' */ | ||
| 91 | } | ||
| 92 | ci->savedpc = *ci->pc; | ||
| 81 | } | 93 | } |
| 82 | ci->savedpc = *ci->pc; | ||
| 83 | } | 94 | } |
| 84 | 95 | ||
| 85 | 96 | ||
| @@ -370,8 +381,9 @@ StkId luaV_execute (lua_State *L) { | |||
| 370 | for (;;) { | 381 | for (;;) { |
| 371 | const Instruction i = *pc++; | 382 | const Instruction i = *pc++; |
| 372 | StkId ra; | 383 | StkId ra; |
| 373 | if (L->linehook) | 384 | if (L->hookmask >= LUA_MASKLINE && |
| 374 | traceexec(L); | 385 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) |
| 386 | traceexec(L); | ||
| 375 | ra = RA(i); | 387 | ra = RA(i); |
| 376 | lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); | 388 | lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); |
| 377 | lua_assert(L->top == L->ci->top || | 389 | lua_assert(L->top == L->ci->top || |
