From 2877bad4c260d11c22c3b12e633d6b1ca3415789 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 19 Jan 2000 10:00:45 -0200 Subject: [PATCH] new debug API (first version) --- lapi.c | 32 ++------ lapi.h | 8 +- lauxlib.c | 16 ++-- ldblib.c | 155 ++++++++++++++------------------------ ldebug.c | 213 ++++++++++++++++++++++++++++++++--------------------- ldo.c | 43 +++++------ ldo.h | 8 +- liolib.c | 48 ++++++------ lstate.h | 6 +- ltests.c | 6 +- ltm.c | 4 +- luadebug.h | 49 ++++++++---- lvm.c | 6 +- 13 files changed, 286 insertions(+), 308 deletions(-) diff --git a/lapi.c b/lapi.c index 72df1a2a..85ac9328 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.67 1999/12/30 18:27:03 roberto Exp roberto $ +** $Id: lapi.c,v 1.68 2000/01/13 15:56:03 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -30,29 +30,12 @@ const char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" -const lua_Type luaA_normtype[] = { /* ORDER LUA_T */ - LUA_T_USERDATA, LUA_T_NUMBER, LUA_T_STRING, LUA_T_ARRAY, - LUA_T_LPROTO, LUA_T_CPROTO, LUA_T_NIL, - LUA_T_LCLOSURE, LUA_T_CCLOSURE, - LUA_T_LCLOSURE, LUA_T_CCLOSURE, /* LUA_T_LCLMARK, LUA_T_CCLMARK */ - LUA_T_LPROTO, LUA_T_CPROTO /* LUA_T_LMARK, LUA_T_CMARK */ -}; - - -void luaA_setnormalized (TObject *d, const TObject *s) { - d->value = s->value; - d->ttype = luaA_normalizedtype(s); -} - const TObject *luaA_protovalue (const TObject *o) { - switch (luaA_normalizedtype(o)) { + switch (ttype(o)) { case LUA_T_CCLOSURE: case LUA_T_LCLOSURE: return protovalue(o); default: - LUA_ASSERT(L, luaA_normalizedtype(o) == LUA_T_LPROTO || - luaA_normalizedtype(o) == LUA_T_CPROTO, - "invalid `function'"); return o; } } @@ -107,7 +90,7 @@ int lua_callfunction (lua_State *L, lua_Object function) { return 1; else { luaD_openstack(L, L->Cstack.base); - luaA_setnormalized(L->Cstack.base, function); + *L->Cstack.base = *function; return luaD_protectedrun(L); } } @@ -248,12 +231,7 @@ int lua_equal(lua_State *L, lua_Object o1, lua_Object o2) { UNUSED(L); if (o1 == LUA_NOOBJECT || o2 == LUA_NOOBJECT) return (o1 == o2); - else { - TObject obj1, obj2; - luaA_setnormalized(&obj1, o1); - luaA_setnormalized(&obj2, o2); - return luaO_equalObj(&obj1, &obj2); - } + else return luaO_equalObj(o1, o2); } @@ -344,7 +322,7 @@ void luaA_pushobject (lua_State *L, const TObject *o) { void lua_pushobject (lua_State *L, lua_Object o) { if (o == LUA_NOOBJECT) lua_error(L, "API error - attempt to push a NOOBJECT"); - luaA_setnormalized(L->top, o); + *L->top = *o; incr_top; } diff --git a/lapi.h b/lapi.h index 9dc630e9..469fb272 100644 --- a/lapi.h +++ b/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 1.11 1999/12/14 18:33:29 roberto Exp roberto $ +** $Id: lapi.h,v 1.12 1999/12/23 18:19:57 roberto Exp roberto $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -11,12 +11,6 @@ #include "lobject.h" -extern const lua_Type luaA_normtype[]; - -#define luaA_normalizedtype(o) (luaA_normtype[-ttype(o)]) - - -void luaA_setnormalized (TObject *d, const TObject *s); void luaA_checkCparams (lua_State *L, int nParams); const TObject *luaA_protovalue (const TObject *o); void luaA_pushobject (lua_State *L, const TObject *o); diff --git a/lauxlib.c b/lauxlib.c index 978eda04..a85064da 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.23 1999/12/27 17:33:22 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.24 1999/12/28 11:52:49 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -31,14 +31,14 @@ int luaL_findstring (const char *name, const char *const list[]) { } void luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Function f = lua_stackedfunction(L, 0); - const char *funcname; - lua_getobjname(L, f, &funcname); - narg -= lua_nups(L, f); - if (funcname == NULL) - funcname = "?"; + lua_Dbgactreg ar; + lua_getstack(L, 0, &ar); + lua_getinfo(L, "nu", &ar); + narg -= ar.nups; + if (ar.name == NULL) + ar.name = "?"; luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)", - narg, funcname, extramsg); + narg, ar.name, extramsg); } diff --git a/ldblib.c b/ldblib.c index 028f6210..3634d213 100644 --- a/ldblib.c +++ b/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.8 1999/11/22 17:39:51 roberto Exp roberto $ +** $Id: ldblib.c,v 1.9 1999/12/21 18:04:41 roberto Exp roberto $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -33,113 +33,73 @@ static void settabsi (lua_State *L, lua_Object t, const char *i, int v) { } -static lua_Object getfuncinfo (lua_State *L, lua_Object func) { - lua_Object result = lua_createtable(L); - const char *str; - int line; - lua_funcinfo(L, func, &str, &line); - if (line == -1) /* C function? */ - settabss(L, result, "kind", "C"); - else if (line == 0) { /* "main"? */ - settabss(L, result, "kind", "chunk"); - settabss(L, result, "source", str); - } - else { /* Lua function */ - settabss(L, result, "kind", "Lua"); - settabsi(L, result, "def_line", line); - settabss(L, result, "source", str); - } - if (line != 0) { /* is it not a "main"? */ - const char *kind = lua_getobjname(L, func, &str); - if (*kind) { - settabss(L, result, "name", str); - settabss(L, result, "where", kind); - } - } - return result; +static void settabso (lua_State *L, lua_Object t, const char *i, lua_Object v) { + lua_pushobject(L, t); + lua_pushstring(L, i); + lua_pushobject(L, v); + lua_settable(L); } static void getstack (lua_State *L) { - lua_Object func = lua_stackedfunction(L, luaL_check_int(L, 1)); - if (func == LUA_NOOBJECT) /* level out of range? */ + lua_Dbgactreg ar; + if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ return; else { - lua_Object result = getfuncinfo(L, func); - int currline = lua_currentline(L, func); - if (currline > 0) - settabsi(L, result, "current", currline); - lua_pushobject(L, result); - lua_pushstring(L, "func"); - lua_pushobject(L, func); - lua_settable(L); /* result.func = func */ - lua_pushobject(L, result); - } -} + const char *options = luaL_check_string(L, 2); + lua_Object res = lua_createtable(L); + if (!lua_getinfo(L, options, &ar)) + luaL_argerror(L, 2, "invalid option"); + for ( ;*options; options++) { + switch (*options) { + case 'S': + settabss(L, res, "source", ar.source); + settabsi(L, res, "linedefined", ar.linedefined); + settabss(L, res, "what", ar.what); + break; + case 'l': + settabsi(L, res, "currentline", ar.currentline); + break; + case 'u': + settabsi(L, res, "nups", ar.nups); + break; + case 'n': + settabss(L, res, "name", ar.name); + settabss(L, res, "namewhat", ar.namewhat); + break; + case 'f': + settabso(L, res, "func", ar.func); + break; - -static void funcinfo (lua_State *L) { - lua_pushobject(L, getfuncinfo(L, luaL_functionarg(L, 1))); -} - - -static int findlocal (lua_State *L, lua_Object func, int arg) { - lua_Object v = lua_getparam(L, arg); - if (lua_isnumber(L, v)) - return (int)lua_getnumber(L, v); - else { - const char *name = luaL_check_string(L, arg); - int i = 0; - int result = -1; - const char *vname; - while (lua_getlocal(L, func, ++i, &vname) != LUA_NOOBJECT) { - if (strcmp(name, vname) == 0) - result = i; /* keep looping to get the last var with this name */ + } } - if (result == -1) - luaL_verror(L, "no local variable `%.50s' at given level", name); - return result; + lua_pushobject(L, res); } } - + static void getlocal (lua_State *L) { - lua_Object func = lua_stackedfunction(L, luaL_check_int(L, 1)); - lua_Object val; - const char *name; - if (func == LUA_NOOBJECT) /* level out of range? */ - return; /* return nil */ - else if (lua_getparam(L, 2) != LUA_NOOBJECT) { /* 2nd argument? */ - if ((val = lua_getlocal(L, func, findlocal(L, func, 2), &name)) != LUA_NOOBJECT) { - lua_pushobject(L, val); - lua_pushstring(L, name); - } - /* else return nil */ - } - else { /* collect all locals in a table */ - lua_Object result = lua_createtable(L); - int i; - for (i=1; ;i++) { - if ((val = lua_getlocal(L, func, i, &name)) == LUA_NOOBJECT) - break; - lua_pushobject(L, result); - lua_pushstring(L, name); - lua_pushobject(L, val); - lua_settable(L); /* result[name] = value */ - } - lua_pushobject(L, result); + lua_Dbgactreg ar; + lua_Dbglocvar lvar; + if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ + luaL_argerror(L, 1, "level out of range"); + lvar.index = luaL_check_int(L, 2); + if (lua_getlocal(L, &ar, &lvar)) { + lua_pushstring(L, lvar.name); + lua_pushobject(L, lvar.value); } } static void setlocal (lua_State *L) { - lua_Object func = lua_stackedfunction(L, luaL_check_int(L, 1)); - int numvar; - luaL_arg_check(L, func != LUA_NOOBJECT, 1, "level out of range"); - numvar = findlocal(L, func, 2); - lua_pushobject(L, luaL_nonnullarg(L, 3)); - if (!lua_setlocal(L, func, numvar)) - lua_error(L, "no such local variable"); + lua_Dbgactreg ar; + lua_Dbglocvar lvar; + if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ + luaL_argerror(L, 1, "level out of range"); + lvar.index = luaL_check_int(L, 2); + lvar.value = luaL_nonnullarg(L, 3); + if (lua_setlocal(L, &ar, &lvar)) + lua_pushstring(L, lvar.name); } @@ -149,21 +109,17 @@ static int callhook = LUA_NOREF; /* Lua reference to call hook function */ -static void linef (lua_State *L, int line) { +static void linef (lua_State *L, lua_Dbgactreg *ar) { if (linehook != LUA_NOREF) { - lua_pushnumber(L, line); + lua_pushnumber(L, ar->currentline); lua_callfunction(L, lua_getref(L, linehook)); } } -static void callf (lua_State *L, lua_Function f, const char *file, int line) { +static void callf (lua_State *L, lua_Dbgactreg *ar) { if (callhook != LUA_NOREF) { - if (f != LUA_NOOBJECT) { - lua_pushobject(L, f); - lua_pushstring(L, file); - lua_pushnumber(L, line); - } + lua_pushstring(L, ar->event); lua_callfunction(L, lua_getref(L, callhook)); } } @@ -200,7 +156,6 @@ static void setlinehook (lua_State *L) { static const struct luaL_reg dblib[] = { - {"funcinfo", funcinfo}, {"getlocal", getlocal}, {"getstack", getstack}, {"setcallhook", setcallhook}, diff --git a/ldebug.c b/ldebug.c index 5d0b811e..504dae90 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.3 1999/12/29 16:31:15 roberto Exp roberto $ +** $Id: ldebug.c,v 1.4 1999/12/30 18:28:40 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -10,6 +10,7 @@ #include "lapi.h" #include "lauxlib.h" #include "ldebug.h" +#include "ldo.h" #include "lfunc.h" #include "lobject.h" #include "lstate.h" @@ -19,22 +20,38 @@ #include "luadebug.h" -static int hasdebuginfo (lua_State *L, lua_Function f) { +static const lua_Type normtype[] = { /* ORDER LUA_T */ + LUA_T_USERDATA, LUA_T_NUMBER, LUA_T_STRING, LUA_T_ARRAY, + LUA_T_LPROTO, LUA_T_CPROTO, LUA_T_NIL, + LUA_T_LCLOSURE, LUA_T_CCLOSURE, + LUA_T_LCLOSURE, LUA_T_CCLOSURE, /* LUA_T_LCLMARK, LUA_T_CCLMARK */ + LUA_T_LPROTO, LUA_T_CPROTO /* LUA_T_LMARK, LUA_T_CMARK */ +}; + + +static void setnormalized (TObject *d, const TObject *s) { + d->value = s->value; + d->ttype = normtype[-ttype(s)]; +} + + + +static int hasdebuginfo (lua_State *L, StkId f) { return (f+1 < L->top && (f+1)->ttype == LUA_T_LINE); } -lua_LHFunction lua_setlinehook (lua_State *L, lua_LHFunction func) { - lua_LHFunction old = L->linehook; - L->linehook = func; - return old; +lua_Dbghook lua_setcallhook (lua_State *L, lua_Dbghook func) { + lua_Dbghook oldhook = L->callhook; + L->callhook = func; + return oldhook; } -lua_CHFunction lua_setcallhook (lua_State *L, lua_CHFunction func) { - lua_CHFunction old = L->callhook; - L->callhook = func; - return old; +lua_Dbghook lua_setlinehook (lua_State *L, lua_Dbghook func) { + lua_Dbghook oldhook = L->linehook; + L->linehook = func; + return oldhook; } @@ -45,7 +62,7 @@ int lua_setdebug (lua_State *L, int debug) { } -static lua_Function aux_stackedfunction (lua_State *L, int level, StkId top) { +static StkId aux_stackedfunction (lua_State *L, int level, StkId top) { int i; for (i = (top-1)-L->stack; i>=0; i--) { if (is_T_MARK(L->stack[i].ttype)) { @@ -54,18 +71,23 @@ static lua_Function aux_stackedfunction (lua_State *L, int level, StkId top) { level--; } } - return LUA_NOOBJECT; + return NULL; } -lua_Function lua_stackedfunction (lua_State *L, int level) { - return aux_stackedfunction(L, level, L->top); +int lua_getstack (lua_State *L, int level, lua_Dbgactreg *ar) { + StkId f = aux_stackedfunction(L, level, L->top); + if (f == NULL) return 0; /* there is no such level */ + else { + ar->_func = f; + return 1; + } } static const char *luaG_getname (lua_State *L, const char **name, StkId top) { - lua_Function f = aux_stackedfunction(L, 0, top); - if (f == LUA_NOOBJECT || !hasdebuginfo(L, f) || ttype(f+2) == LUA_T_NIL) + StkId f = aux_stackedfunction(L, 0, top); + if (f == NULL || !hasdebuginfo(L, f) || ttype(f+2) == LUA_T_NIL) return ""; /* no name available */ else { int i = (f+2)->value.i; @@ -79,10 +101,10 @@ static const char *luaG_getname (lua_State *L, const char **name, StkId top) { } -int lua_nups (lua_State *L, lua_Function f) { - UNUSED(L); - switch (luaA_normalizedtype(f)) { +static int lua_nups (StkId f) { + switch (ttype(f)) { case LUA_T_LCLOSURE: case LUA_T_CCLOSURE: + case LUA_T_LCLMARK: case LUA_T_CCLMARK: return f->value.cl->nelems; default: return 0; @@ -90,67 +112,66 @@ int lua_nups (lua_State *L, lua_Function f) { } -int lua_currentline (lua_State *L, lua_Function f) { +static int lua_currentline (lua_State *L, StkId f) { return hasdebuginfo(L, f) ? (f+1)->value.i : -1; } -lua_Object lua_getlocal (lua_State *L, lua_Function f, int local_number, - const char **name) { - /* check whether `f' is a Lua function */ - if (lua_tag(L, f) != LUA_T_LPROTO) - return LUA_NOOBJECT; - else { - TProtoFunc *fp = luaA_protovalue(f)->value.tf; - *name = luaF_getlocalname(fp, local_number, lua_currentline(L, f)); - if (*name) { - /* if "*name", there must be a LUA_T_LINE and a NAME */ - /* therefore, f+3 points to function base */ - LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); - return luaA_putluaObject(L, (f+3)+(local_number-1)); - } - else - return LUA_NOOBJECT; - } +static TProtoFunc *getluaproto (StkId f) { + if (ttype(f) == LUA_T_LMARK) + return f->value.tf; + else if (ttype(f) == LUA_T_LCLMARK) + return protovalue(f)->value.tf; + else return NULL; } -int lua_setlocal (lua_State *L, lua_Function f, int local_number) { - /* check whether `f' is a Lua function */ - if (lua_tag(L, f) != LUA_T_LPROTO) - return 0; - else { - TProtoFunc *fp = luaA_protovalue(f)->value.tf; - const char *name = luaF_getlocalname(fp, local_number, - lua_currentline(L, f)); - luaA_checkCparams(L, 1); - --L->top; - if (name) { - LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); - *((f+3)+(local_number-1)) = *L->top; - return 1; - } - else - return 0; - } +int lua_getlocal (lua_State *L, const lua_Dbgactreg *ar, lua_Dbglocvar *v) { + StkId f = ar->_func; + TProtoFunc *fp = getluaproto(f); + if (!fp) return 0; /* `f' is not a Lua function? */ + v->name = luaF_getlocalname(fp, v->index, lua_currentline(L, f)); + if (!v->name) return 0; + /* if `name', there must be a LUA_T_LINE and a NAME */ + /* therefore, f+3 points to function base */ + LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); + v->value = luaA_putluaObject(L, (f+3)+(v->index-1)); + return 1; } -void lua_funcinfo (lua_State *L, lua_Object func, - const char **source, int *linedefined) { - if (!lua_isfunction(L, func)) - lua_error(L, "API error - `funcinfo' called with a non-function value"); - else { - const TObject *f = luaA_protovalue(func); - if (luaA_normalizedtype(f) == LUA_T_LPROTO) { - *source = tfvalue(f)->source->str; - *linedefined = tfvalue(f)->lineDefined; - } - else { - *source = "(C)"; - *linedefined = -1; - } +int lua_setlocal (lua_State *L, const lua_Dbgactreg *ar, lua_Dbglocvar *v) { + StkId f = ar->_func; + TProtoFunc *fp = getluaproto(f); + if (!fp) return 0; /* `f' is not a Lua function? */ + v->name = luaF_getlocalname(fp, v->index, lua_currentline(L, f)); + if (!v->name) return 0; + LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); + *((f+3)+(v->index-1)) = *v->value; + return 1; +} + + +static void lua_funcinfo (lua_Dbgactreg *ar) { + StkId func = ar->_func; + switch (ttype(func)) { + case LUA_T_LPROTO: case LUA_T_LMARK: + ar->source = tfvalue(func)->source->str; + ar->linedefined = tfvalue(func)->lineDefined; + ar->what = "Lua"; + break; + case LUA_T_LCLOSURE: case LUA_T_LCLMARK: + ar->source = tfvalue(protovalue(func))->source->str; + ar->linedefined = tfvalue(protovalue(func))->lineDefined; + ar->what = "Lua"; + break; + default: + ar->source = "(C)"; + ar->linedefined = -1; + ar->what = "C"; } + if (ar->linedefined == 0) + ar->what = "main"; } @@ -159,28 +180,56 @@ static int checkfunc (lua_State *L, TObject *o) { } -const char *lua_getobjname (lua_State *L, lua_Object o, const char **name) { +static void lua_getobjname (lua_State *L, StkId f, lua_Dbgactreg *ar) { GlobalVar *g; - if (is_T_MARK(ttype(o))) { /* `o' is an active function? */ - /* look for caller debug information */ - const char *kind = luaG_getname(L, name, o); - if (*kind) return kind; - /* else go through */ - } + ar->namewhat = luaG_getname(L, &ar->name, f); /* caller debug information */ + if (*ar->namewhat) return; /* try to find a name for given function */ - luaA_setnormalized(L->top, o); /* to be used by `checkfunc' */ + setnormalized(L->top, f); /* to be used by `checkfunc' */ for (g=L->rootglobal; g; g=g->next) { if (checkfunc(L, &g->value)) { - *name = g->name->str; - return "global"; + ar->name = g->name->str; + ar->namewhat = "global"; + return; } } /* not found: try tag methods */ - if ((*name = luaT_travtagmethods(L, checkfunc)) != NULL) - return "tag-method"; - else return ""; /* not found at all */ + if ((ar->name = luaT_travtagmethods(L, checkfunc)) != NULL) + ar->namewhat = "tag-method"; + else ar->namewhat = ""; /* not found at all */ } + +int lua_getinfo (lua_State *L, const char *what, lua_Dbgactreg *ar) { + StkId func = ar->_func; + LUA_ASSERT(L, is_T_MARK(ttype(func)), "invalid activation record"); + for ( ;*what; what++) { + switch (*what) { + case 'S': + lua_funcinfo(ar); + break; + case 'l': + ar->currentline = lua_currentline(L, func); + break; + case 'u': + ar->nups = lua_nups(func); + break; + case 'n': + lua_getobjname(L, func, ar); + break; + case 'f': + setnormalized(L->top, func); + incr_top; + ar->func = luaA_putObjectOnTop(L); + break; + default: return 0; /* invalid option */ + } + } + return 1; +} + + + static void call_index_error (lua_State *L, TObject *o, const char *tp, const char *v) { const char *name; diff --git a/ldo.c b/ldo.c index 3b06b8d7..7bc45199 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.64 1999/12/30 18:40:57 roberto Exp roberto $ +** $Id: ldo.c,v 1.65 2000/01/13 15:56:03 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -55,8 +55,9 @@ void luaD_checkstack (lua_State *L, int n) { lua_error(L, "BAD STACK OVERFLOW! DATA CORRUPTED!!"); } else { + lua_Dbgactreg dummy; L->stack_last += EXTRA_STACK; /* to be used by error message */ - if (lua_stackedfunction(L, L->stacksize/SLOTS_PER_F) == LUA_NOOBJECT) { + if (lua_getstack(L, L->stacksize/SLOTS_PER_F, &dummy) == 0) { /* too few funcs on stack: doesn't look like a recursion loop */ lua_error(L, "Lua2C - C2Lua overflow"); } @@ -100,13 +101,17 @@ void luaD_openstack (lua_State *L, StkId pos) { } -void luaD_lineHook (lua_State *L, int line) { +void luaD_lineHook (lua_State *L, StkId func, int line) { if (L->allowhooks) { + lua_Dbgactreg ar; struct C_Lua_Stack oldCLS = L->Cstack; StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->top; L->Cstack.num = 0; + ar._func = func; + ar.event = "line"; + ar.currentline = line; L->allowhooks = 0; /* cannot call hooks inside a hook */ - (*L->linehook)(L, line); + (*L->linehook)(L, &ar); L->allowhooks = 1; L->top = old_top; L->Cstack = oldCLS; @@ -114,29 +119,17 @@ void luaD_lineHook (lua_State *L, int line) { } -void luaD_callHook (lua_State *L, StkId func, lua_CHFunction callhook, - int isreturn) { +void luaD_callHook (lua_State *L, StkId func, lua_Dbghook callhook, + const char *event) { if (L->allowhooks) { + lua_Dbgactreg ar; struct C_Lua_Stack oldCLS = L->Cstack; StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->top; L->Cstack.num = 0; + ar._func = func; + ar.event = event; L->allowhooks = 0; /* cannot call hooks inside a hook */ - if (isreturn) - callhook(L, LUA_NOOBJECT, "(return)", 0); - else { - switch (ttype(func)) { - case LUA_T_LPROTO: - callhook(L, func, tfvalue(func)->source->str, - tfvalue(func)->lineDefined); - break; - case LUA_T_LCLOSURE: - callhook(L, func, tfvalue(protovalue(func))->source->str, - tfvalue(protovalue(func))->lineDefined); - break; - default: - callhook(L, func, "(C)", -1); - } - } + callhook(L, &ar); L->allowhooks = 1; L->top = old_top; L->Cstack = oldCLS; @@ -157,7 +150,7 @@ static StkId callC (lua_State *L, lua_CFunction f, StkId base) { L->Cstack.lua2C = base; L->Cstack.base = L->top; if (L->callhook) - luaD_callHook(L, base-1, L->callhook, 0); + luaD_callHook(L, base-1, L->callhook, "call"); (*f)(L); /* do the actual call */ firstResult = L->Cstack.base; L->Cstack = oldCLS; @@ -195,7 +188,7 @@ void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { */ void luaD_call (lua_State *L, StkId func, int nResults) { StkId firstResult; - lua_CHFunction callhook = L->callhook; + lua_Dbghook callhook = L->callhook; retry: /* for `function' tag method */ switch (ttype(func)) { case LUA_T_CPROTO: @@ -228,7 +221,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { } } if (callhook) /* same hook that was active at entry */ - luaD_callHook(L, NULL, callhook, 1); /* `return' hook */ + luaD_callHook(L, func, callhook, "return"); /* adjust the number of results */ if (nResults == MULT_RET) nResults = L->top - firstResult; diff --git a/ldo.h b/ldo.h index bd15f039..91c7c787 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.15 1999/12/21 18:04:41 roberto Exp roberto $ +** $Id: ldo.h,v 1.16 1999/12/30 18:28:40 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -26,9 +26,9 @@ void luaD_init (lua_State *L, int stacksize); void luaD_adjusttop (lua_State *L, StkId base, int extra); void luaD_openstack (lua_State *L, StkId pos); -void luaD_callHook (lua_State *L, StkId func, lua_CHFunction callhook, - int isreturn); -void luaD_lineHook (lua_State *L, int line); +void luaD_callHook (lua_State *L, StkId func, lua_Dbghook callhook, + const char *event); +void luaD_lineHook (lua_State *L, StkId func, int line); void luaD_call (lua_State *L, StkId func, int nResults); void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); int luaD_protectedrun (lua_State *L); diff --git a/liolib.c b/liolib.c index b58bcaff..e9f114fe 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 1.54 1999/12/28 11:52:49 roberto Exp roberto $ +** $Id: liolib.c,v 1.55 1999/12/30 18:28:40 roberto Exp roberto $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -529,53 +529,49 @@ static void io_debug (lua_State *L) { static void errorfb (lua_State *L) { char buff[MAXMESSAGE]; int level = 1; /* skip level 0 (it's this function) */ - lua_Object func; + lua_Dbgactreg ar; + lua_Object alertfunc = lua_rawgetglobal(L, "_ALERT"); sprintf(buff, "error: %.200s\n", lua_getstring(L, lua_getparam(L, 1))); - while ((func = lua_stackedfunction(L, level++)) != LUA_NOOBJECT) { - const char *name; - int currentline; - const char *chunkname; + while (lua_getstack(L, level++, &ar)) { char buffchunk[MAXSRC]; - int linedefined; - lua_funcinfo(L, func, &chunkname, &linedefined); - luaL_chunkid(buffchunk, chunkname, sizeof(buffchunk)); + lua_getinfo(L, "Snl", &ar); + luaL_chunkid(buffchunk, ar.source, sizeof(buffchunk)); if (level == 2) strcat(buff, "Active Stack:\n"); strcat(buff, " "); if (strlen(buff) > MAXMESSAGE-MESSAGESIZE) { strcat(buff, "...\n"); break; /* buffer is full */ } - switch (*lua_getobjname(L, func, &name)) { - case 'g': case 'l': - sprintf(buff+strlen(buff), "function `%.50s'", name); + switch (*ar.namewhat) { + case 'g': case 'l': /* global, local */ + sprintf(buff+strlen(buff), "function `%.50s'", ar.name); break; - case 'f': - sprintf(buff+strlen(buff), "method `%.50s'", name); + case 'f': /* field */ + sprintf(buff+strlen(buff), "method `%.50s'", ar.name); break; - case 't': - sprintf(buff+strlen(buff), "`%.50s' tag method", name); + case 't': /* tag method */ + sprintf(buff+strlen(buff), "`%.50s' tag method", ar.name); break; default: { - if (linedefined == 0) + if (*ar.what == 'm') /* main? */ sprintf(buff+strlen(buff), "main of %.70s", buffchunk); - else if (linedefined < 0) + else if (*ar.what == 'C') /* C function? */ sprintf(buff+strlen(buff), "%.70s", buffchunk); else sprintf(buff+strlen(buff), "function <%d:%.70s>", - linedefined, buffchunk); - chunkname = NULL; + ar.linedefined, buffchunk); + ar.source = NULL; } } - if ((currentline = lua_currentline(L, func)) > 0) - sprintf(buff+strlen(buff), " at line %d", currentline); - if (chunkname) + if (ar.currentline > 0) + sprintf(buff+strlen(buff), " at line %d", ar.currentline); + if (ar.source) sprintf(buff+strlen(buff), " [%.70s]", buffchunk); strcat(buff, "\n"); } - func = lua_rawgetglobal(L, "_ALERT"); - if (lua_isfunction(L, func)) { /* avoid error loop if _ALERT is not defined */ + if (lua_isfunction(L, alertfunc)) { /* avoid loop if _ALERT is not defined */ lua_pushstring(L, buff); - lua_callfunction(L, func); + lua_callfunction(L, alertfunc); } } diff --git a/lstate.h b/lstate.h index c4c8271e..f24f2d0a 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.26 1999/12/21 18:04:41 roberto Exp roberto $ +** $Id: lstate.h,v 1.27 1999/12/27 17:33:22 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -76,8 +76,8 @@ struct lua_State { unsigned long GCthreshold; unsigned long nblocks; /* number of `blocks' currently allocated */ int debug; - lua_CHFunction callhook; - lua_LHFunction linehook; + lua_Dbghook callhook; + lua_Dbghook linehook; int allowhooks; }; diff --git a/ltests.c b/ltests.c index 658c9deb..a91d51d6 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.3 1999/12/27 17:33:22 roberto Exp roberto $ +** $Id: ltests.c,v 1.4 2000/01/13 16:30:47 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -230,10 +230,6 @@ static void testC (lua_State *L) { int n = getreg(L, &pc); lua_settagmethod(L, (int)lua_getnumber(L, reg[n]), getname(&pc)); } - else if EQ("getfunc") { - int n = getreg(L, &pc); - reg[n] = lua_stackedfunction(L, getnum(&pc)); - } else if EQ("beginblock") { lua_beginblock(L); } diff --git a/ltm.c b/ltm.c index 615cdfe4..93a806d8 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 1.29 1999/11/22 13:12:07 roberto Exp roberto $ +** $Id: ltm.c,v 1.30 1999/12/23 18:19:57 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -108,8 +108,6 @@ int luaT_effectivetag (const TObject *o) { LUA_T_USERDATA, LUA_T_NUMBER, LUA_T_STRING, LUA_T_ARRAY, LUA_T_LPROTO, LUA_T_CPROTO, LUA_T_NIL, LUA_T_LPROTO, LUA_T_CPROTO, /* LUA_T_LCLOSURE, LUA_T_CCLOSURE */ - LUA_T_LPROTO, LUA_T_CPROTO, /* LUA_T_LCLMARK, LUA_T_CCLMARK */ - LUA_T_LPROTO, LUA_T_CPROTO /* LUA_T_LMARK, LUA_T_CMARK */ }; int t; switch (t = ttype(o)) { diff --git a/luadebug.h b/luadebug.h index 29c5a39c..9c3820a0 100644 --- a/luadebug.h +++ b/luadebug.h @@ -1,5 +1,5 @@ /* -** $Id: luadebug.h,v 1.7 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: luadebug.h,v 1.8 1999/11/22 13:12:07 roberto Exp roberto $ ** Debugging API ** See Copyright Notice in lua.h */ @@ -11,25 +11,44 @@ #include "lua.h" -typedef lua_Object lua_Function; +typedef struct lua_Dbgactreg lua_Dbgactreg; /* activation record */ +typedef struct lua_Dbglocvar lua_Dbglocvar; /* local variable */ -typedef void (*lua_LHFunction) (lua_State *L, int line); -typedef void (*lua_CHFunction) (lua_State *L, lua_Function func, const char *file, int line); +typedef void (*lua_Dbghook) (lua_State *L, lua_Dbgactreg *ar); -lua_Function lua_stackedfunction (lua_State *L, int level); -void lua_funcinfo (lua_State *L, lua_Object func, const char **source, int *linedefined); -int lua_currentline (lua_State *L, lua_Function func); -const char *lua_getobjname (lua_State *L, lua_Object o, const char **name); -lua_Object lua_getlocal (lua_State *L, lua_Function func, int local_number, - const char **name); -int lua_setlocal (lua_State *L, lua_Function func, int local_number); +int lua_getstack (lua_State *L, int level, lua_Dbgactreg *ar); +int lua_getinfo (lua_State *L, const char *what, lua_Dbgactreg *ar); +int lua_getlocal (lua_State *L, const lua_Dbgactreg *ar, lua_Dbglocvar *v); +int lua_setlocal (lua_State *L, const lua_Dbgactreg *ar, lua_Dbglocvar *v); -int lua_nups (lua_State *L, lua_Function func); - -lua_LHFunction lua_setlinehook (lua_State *L, lua_LHFunction func); -lua_CHFunction lua_setcallhook (lua_State *L, lua_CHFunction func); int lua_setdebug (lua_State *L, int debug); +lua_Dbghook lua_setcallhook (lua_State *L, lua_Dbghook func); +lua_Dbghook lua_setlinehook (lua_State *L, lua_Dbghook func); + + + +struct lua_Dbgactreg { + const char *event; /* `call', `return' */ + const char *source; /* (S) */ + int linedefined; /* (S) */ + const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ + int currentline; /* (l) */ + const char *name; /* (n) */ + const char *namewhat; /* (n) global, tag method, local, field */ + int nups; /* (u) number of upvalues */ + lua_Object func; /* (f) function being executed */ + /* private part */ + lua_Object _func; /* active function */ +}; + + +struct lua_Dbglocvar { + int index; + const char *name; + lua_Object value; +}; + #endif diff --git a/lvm.c b/lvm.c index bc04871c..258068a5 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.78 1999/12/30 18:28:40 roberto Exp roberto $ +** $Id: lvm.c,v 1.79 2000/01/13 15:56:03 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -308,7 +308,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, register const Byte *pc = tf->code; const TObject *consts = tf->consts; if (L->callhook) - luaD_callHook(L, base-1, L->callhook, 0); + luaD_callHook(L, base-1, L->callhook, "call"); luaD_checkstack(L, (*pc++)+EXTRA_STACK); if (*pc < ZEROVARARG) luaD_adjusttop(L, base, *(pc++)); @@ -617,7 +617,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, (base-2)->value.i = aux; if (L->linehook) { L->top = top; - luaD_lineHook(L, aux); + luaD_lineHook(L, base-3, aux); } break;