Browse Source

new debug API (first version)

Roberto Ierusalimschy 25 years ago
parent
commit
2877bad4c2
13 changed files with 287 additions and 309 deletions
  1. 5 27
      lapi.c
  2. 1 7
      lapi.h
  3. 8 8
      lauxlib.c
  4. 56 101
      ldblib.c
  5. 131 82
      ldebug.c
  6. 18 25
      ldo.c
  7. 4 4
      ldo.h
  8. 22 26
      liolib.c
  9. 3 3
      lstate.h
  10. 1 5
      ltests.c
  11. 1 3
      ltm.c
  12. 34 15
      luadebug.h
  13. 3 3
      lvm.c

+ 5 - 27
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;
 }
 

+ 1 - 7
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);

+ 8 - 8
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);
 }
 
 

+ 56 - 101
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);
-  }
-}
-
-
-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 */
+    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;
+
+      }
     }
-    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},

+ 131 - 82
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) {
-  return (f+1 < L->top && (f+1)->ttype == LUA_T_LINE);
+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)];
 }
 
 
-lua_LHFunction lua_setlinehook (lua_State *L, lua_LHFunction func) {
-  lua_LHFunction old = L->linehook;
-  L->linehook = func;
-  return old;
+
+static int hasdebuginfo (lua_State *L, StkId f) {
+  return (f+1 < L->top && (f+1)->ttype == LUA_T_LINE);
 }
 
 
-lua_CHFunction lua_setcallhook (lua_State *L, lua_CHFunction func) {
-  lua_CHFunction old = L->callhook;
+lua_Dbghook lua_setcallhook (lua_State *L, lua_Dbghook func) {
+  lua_Dbghook oldhook = L->callhook;
   L->callhook = func;
-  return old;
+  return oldhook;
+}
+
+
+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;

+ 18 - 25
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;

+ 4 - 4
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);

+ 22 - 26
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);
   }
 }
 

+ 3 - 3
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;
 };
 

+ 1 - 5
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);
     }

+ 1 - 3
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)) {

+ 34 - 15
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

+ 3 - 3
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;