Преглед на файлове

`debug' library can operate over other threads

Roberto Ierusalimschy преди 22 години
родител
ревизия
79fee99024
променени са 1 файла, в които са добавени 92 реда и са изтрити 42 реда
  1. 92 42
      ldblib.c

+ 92 - 42
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.79 2003/03/11 12:24:34 roberto Exp roberto $
+** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -32,24 +32,39 @@ static void settabsi (lua_State *L, const char *i, int v) {
 }
 
 
+static lua_State *getthread (lua_State *L, int *arg) {
+  if (lua_isthread(L, 1)) {
+    *arg = 1;
+    return lua_tothread(L, 1);
+  }
+  else {
+    *arg = 0;
+    return L;
+  }
+}
+
+
 static int getinfo (lua_State *L) {
   lua_Debug ar;
-  const char *options = luaL_optstring(L, 2, "flnSu");
-  if (lua_isnumber(L, 1)) {
-    if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
+  int arg;
+  lua_State *L1 = getthread(L, &arg);
+  const char *options = luaL_optstring(L, arg+2, "flnSu");
+  if (lua_isnumber(L, arg+1)) {
+    if (!lua_getstack(L1, (int)(lua_tonumber(L, arg+1)), &ar)) {
       lua_pushnil(L);  /* level out of range */
       return 1;
     }
   }
-  else if (lua_isfunction(L, 1)) {
+  else if (lua_isfunction(L, arg+1)) {
     lua_pushfstring(L, ">%s", options);
     options = lua_tostring(L, -1);
-    lua_pushvalue(L, 1);
+    lua_pushvalue(L, arg+1);
+    lua_xmove(L, L1, 1);
   }
   else
-    return luaL_argerror(L, 1, "function or level expected");
-  if (!lua_getinfo(L, options, &ar))
-    return luaL_argerror(L, 2, "invalid option");
+    return luaL_argerror(L, arg+1, "function or level expected");
+  if (!lua_getinfo(L1, options, &ar))
+    return luaL_argerror(L, arg+2, "invalid option");
   lua_newtable(L);
   for (; *options; options++) {
     switch (*options) {
@@ -71,7 +86,10 @@ static int getinfo (lua_State *L) {
         break;
       case 'f':
         lua_pushliteral(L, "func");
-        lua_pushvalue(L, -3);
+        if (L == L1)
+          lua_pushvalue(L, -3);
+        else
+          lua_xmove(L1, L, 1);
         lua_rawset(L, -3);
         break;
     }
@@ -81,12 +99,15 @@ static int getinfo (lua_State *L) {
     
 
 static int getlocal (lua_State *L) {
+  int arg;
+  lua_State *L1 = getthread(L, &arg);
   lua_Debug ar;
   const char *name;
-  if (!lua_getstack(L, luaL_checkint(L, 1), &ar))  /* level out of range? */
-    return luaL_argerror(L, 1, "level out of range");
-  name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
+  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
+    return luaL_argerror(L, arg+1, "level out of range");
+  name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
   if (name) {
+    lua_xmove(L1, L, 1);
     lua_pushstring(L, name);
     lua_pushvalue(L, -2);
     return 2;
@@ -99,11 +120,15 @@ static int getlocal (lua_State *L) {
 
 
 static int setlocal (lua_State *L) {
+  int arg;
+  lua_State *L1 = getthread(L, &arg);
   lua_Debug ar;
-  if (!lua_getstack(L, luaL_checkint(L, 1), &ar))  /* level out of range? */
-    return luaL_argerror(L, 1, "level out of range");
-  luaL_checkany(L, 3);
-  lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
+  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
+    return luaL_argerror(L, arg+1, "level out of range");
+  luaL_checkany(L, arg+3);
+  lua_settop(L, arg+3);
+  lua_xmove(L, L1, 1);
+  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
   return 1;
 }
 
@@ -141,6 +166,8 @@ static void hookf (lua_State *L, lua_Debug *ar) {
     {"call", "return", "line", "count", "tail return"};
   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
   lua_rawget(L, LUA_REGISTRYINDEX);
+  lua_pushlightuserdata(L, L);
+  lua_rawget(L, -2);
   if (lua_isfunction(L, -1)) {
     lua_pushstring(L, hooknames[(int)ar->event]);
     if (ar->currentline >= 0)
@@ -149,8 +176,6 @@ static void hookf (lua_State *L, lua_Debug *ar) {
     lua_assert(lua_getinfo(L, "lS", ar));
     lua_call(L, 2, 0);
   }
-  else
-    lua_pop(L, 1);  /* pop result from gettable */
 }
 
 
@@ -174,36 +199,59 @@ static char *unmakemask (int mask, char *smask) {
 }
 
 
+static void gethooktable (lua_State *L) {
+  lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+  lua_rawget(L, LUA_REGISTRYINDEX);
+  if (!lua_istable(L, -1)) {
+    lua_pop(L, 1);
+    lua_newtable(L);
+    lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+    lua_pushvalue(L, -2);
+    lua_rawset(L, LUA_REGISTRYINDEX);
+  }
+}
+
+
 static int sethook (lua_State *L) {
-  if (lua_isnoneornil(L, 1)) {
-    lua_settop(L, 1);
-    lua_sethook(L, NULL, 0, 0);  /* turn off hooks */
+  int arg;
+  lua_State *L1 = getthread(L, &arg);
+  if (lua_isnoneornil(L, arg+1)) {
+    lua_settop(L, arg+1);
+    lua_sethook(L1, NULL, 0, 0);  /* turn off hooks */
   }
   else {
-    const char *smask = luaL_checkstring(L, 2);
-    int count = luaL_optint(L, 3, 0);
-    luaL_checktype(L, 1, LUA_TFUNCTION);
-    lua_sethook(L, hookf, makemask(smask, count), count);
+    const char *smask = luaL_checkstring(L, arg+2);
+    int count = luaL_optint(L, arg+3, 0);
+    luaL_checktype(L, arg+1, LUA_TFUNCTION);
+    lua_sethook(L1, hookf, makemask(smask, count), count);
   }
-  lua_pushlightuserdata(L, (void *)&KEY_HOOK);
-  lua_pushvalue(L, 1);
-  lua_rawset(L, LUA_REGISTRYINDEX);  /* set new hook */
+  gethooktable(L1);
+  lua_pushlightuserdata(L1, L1);
+  lua_pushvalue(L, arg+1);
+  lua_xmove(L, L1, 1);
+  lua_rawset(L1, -3);  /* set new hook */
+  lua_pop(L1, 1);  /* remove hook table */
   return 0;
 }
 
 
 static int gethook (lua_State *L) {
+  int arg;
+  lua_State *L1 = getthread(L, &arg);
   char buff[5];
-  int mask = lua_gethookmask(L);
-  lua_Hook hook = lua_gethook(L);
+  int mask = lua_gethookmask(L1);
+  lua_Hook hook = lua_gethook(L1);
   if (hook != NULL && hook != hookf)  /* external hook? */
     lua_pushliteral(L, "external hook");
   else {
-    lua_pushlightuserdata(L, (void *)&KEY_HOOK);
-    lua_rawget(L, LUA_REGISTRYINDEX);   /* get hook */
+    gethooktable(L1);
+    lua_pushlightuserdata(L1, L1);
+    lua_rawget(L1, -2);   /* get hook */
+    lua_remove(L1, -2);  /* remove hook table */
+    lua_xmove(L1, L, 1);
   }
   lua_pushstring(L, unmakemask(mask, buff));
-  lua_pushnumber(L, (lua_Number)lua_gethookcount(L));
+  lua_pushnumber(L, (lua_Number)lua_gethookcount(L1));
   return 3;
 }
 
@@ -227,27 +275,29 @@ static int debug (lua_State *L) {
 static int errorfb (lua_State *L) {
   int level = 1;  /* skip level 0 (it's this function) */
   int firstpart = 1;  /* still before eventual `...' */
+  int arg;
+  lua_State *L1 = getthread(L, &arg);
   lua_Debug ar;
-  if (lua_gettop(L) == 0)
+  if (lua_gettop(L) == arg)
     lua_pushliteral(L, "");
-  else if (!lua_isstring(L, 1)) return 1;  /* no string message */
+  else if (!lua_isstring(L, arg+1)) return 1;  /* no string message */
   else lua_pushliteral(L, "\n");
   lua_pushliteral(L, "stack traceback:");
-  while (lua_getstack(L, level++, &ar)) {
+  while (lua_getstack(L1, level++, &ar)) {
     if (level > LEVELS1 && firstpart) {
       /* no more than `LEVELS2' more levels? */
-      if (!lua_getstack(L, level+LEVELS2, &ar))
+      if (!lua_getstack(L1, level+LEVELS2, &ar))
         level--;  /* keep going */
       else {
         lua_pushliteral(L, "\n\t...");  /* too many levels */
-        while (lua_getstack(L, level+LEVELS2, &ar))  /* find last levels */
+        while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */
           level++;
       }
       firstpart = 0;
       continue;
     }
     lua_pushliteral(L, "\n\t");
-    lua_getinfo(L, "Snl", &ar);
+    lua_getinfo(L1, "Snl", &ar);
     lua_pushfstring(L, "%s:", ar.short_src);
     if (ar.currentline > 0)
       lua_pushfstring(L, "%d:", ar.currentline);
@@ -268,9 +318,9 @@ static int errorfb (lua_State *L) {
                              ar.short_src, ar.linedefined);
       }
     }
-    lua_concat(L, lua_gettop(L));
+    lua_concat(L, lua_gettop(L) - arg);
   }
-  lua_concat(L, lua_gettop(L));
+  lua_concat(L, lua_gettop(L) - arg);
   return 1;
 }