Make the merged code work again. Also fixs a SEGV.
authorRui Guo <firemeteor.guo@gmail.com>
Wed, 10 Jun 2009 12:22:11 +0000 (10 20:22 +0800)
committerRui Guo <firemeteor.guo@gmail.com>
Wed, 10 Jun 2009 12:22:11 +0000 (10 20:22 +0800)
1. Properly push function according to the new lua_handler structure.
2. Never return without balancing the stack!

src/lua.c

index 5f607b6..ac4c59f 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -297,6 +297,7 @@ struct_register(lua_State *L, const char *name, const luaL_reg fn_methods[], con
   lua_pushcclosure(L, newindex_handler, 1);
   lua_rawset(L, metatable);     /* metatable.__newindex = newindex_handler */
 
+  /* FIXME: Why do we leave an element on the stack? */
   lua_pop(L, 1);                /* drop metatable */
   return 1;                     /* return methods on the stack */
 }
@@ -658,7 +659,7 @@ static int
 screen_append_msg(lua_State *L)
 {
   const char *msg, *color;
-  int len;
+  unsigned int len;
   msg = luaL_checklstring(L, 1, &len);
   if (lua_isnil(L, 2))
     color = NULL;
@@ -737,7 +738,16 @@ int LuaInit(void)
 
   /* To store handler funcs */
   luaL_getmetatable(L, "screen");
-  lua_pushstring(L, "_handlers");
+  /* two kinds of info in this table:
+   * _funckey[func]->key
+   * _funckey[key]->refcnt */
+  lua_pushstring(L, "_funckey");
+  lua_newtable(L);
+  lua_rawset(L, -3);
+  /* two kinds of info in this table:
+   * _keyfunc[key]->func
+   * _keyfunc[func]->name */
+  lua_pushstring(L, "_keyfunc");
   lua_newtable(L);
   lua_rawset(L, -3);
   lua_pop(L, 1);
@@ -770,7 +780,10 @@ LuaCallProcess(const char *name, struct fn_def defs[])
 
   lua_getfield(L, LUA_GLOBALSINDEX, name);
   if (lua_isnil(L, -1))
-    return 0;
+    {
+      lua_pop(L,1);
+      return 0;
+    }
   for (argc = 0; defs[argc].push_fn; argc++)
     defs[argc].push_fn(L, defs[argc].value);
   if (lua_pcall(L, argc, 0, 0) == LUA_ERRRUN && lua_isstring(L, -1))
@@ -870,6 +883,7 @@ int LuaCall(char *func, char **argv)
   lua_getfield(L, LUA_GLOBALSINDEX, func);
   if (lua_isnil(L, -1))
     {
+      lua_pop(L, 1);
       lua_pushstring(L, "Could not find the script function\n");
       LuaShowErr(L);
       return 0;
@@ -890,19 +904,37 @@ int LuaCall(char *func, char **argv)
   return 1;
 }
 
+/* Push nil if failed */
+void
+LuaPushHandler(lua_State *L, struct lua_handler * lh)
+{
+  if (lh->type == LUA_HANDLER_TYPE_N)
+    lua_getfield(L, LUA_GLOBALSINDEX, lh->u.name);
+  else
+    {
+      luaL_getmetatable(L, "screen");
+      lua_pushstring(L, "_keyfunc");
+      lua_rawget(L, -2);
+      lua_rawgeti(L, -1, lh->u.reference);
+      lua_replace(L, -3);
+      lua_pop(L, 1);
+    }
+}
+
 static int
 LuaDispatch(void *handler, const char *params, va_list va)
 {
   struct lua_handler *lh = handler;
   int argc, retvalue;
 
-  if (lh->type == LUA_HANDLER_TYPE_N)
-    lua_getfield(L, LUA_GLOBALSINDEX, lh->u.name);
-  else
-    lua_rawgeti(L, LUA_REGISTRYINDEX, lh->u.reference);
+  StackDump(L, "before dispatch");
 
+  LuaPushHandler(L, lh);
   if (lua_isnil(L, -1))
-    return 0;
+    {
+      lua_pop(L, 1);
+      return 0;
+    }
   argc = LuaPushParams(L, params, va);
 
   if (lua_pcall(L, argc, 1, 0) == LUA_ERRRUN && lua_isstring(L, -1))
@@ -944,14 +976,14 @@ LuaCheckHandler(lua_State *L, int idx, int reg)
     }
   else if (lua_isfunction(L, idx))
     {
-      char buf[20];
       int key, htable;
       if (idx < 0)
         idx = lua_gettop(L) + 1 - idx;
 
       luaL_getmetatable(L, "screen");
-      lua_pushstring(L, "_handlers");
+      lua_pushstring(L, "_funckey");
       lua_rawget(L, -2);
+      /* FIXME: Do we need to balance the stack here? */
       if (lua_isnil(L, -1))
         luaL_error(L, "Fatal! Should not happen! Fail to get global handler table!");
       /* Map func to unique key and do reference count */
@@ -961,13 +993,26 @@ LuaCheckHandler(lua_State *L, int idx, int reg)
       if (lua_isnil(L, -1))
         {
           /* not found */
+          int kf;
           if (!reg)
-            return NULL;
+            {
+              lua_pop(L, 3); 
+              return NULL;
+            }
+          lua_pushstring(L, "_keyfunc");
+          lua_rawget(L, -4);
+          kf = lua_gettop(L);
+
           lua_pushinteger(L, 1);
           key = luaL_ref(L, htable); /*htable[key] = 1*/
           lua_pushvalue(L, idx);
           lua_pushinteger(L, key);
           lua_settable(L, htable); /*htable[func]=key*/
+
+          lua_pushinteger(L, key);
+          lua_pushvalue(L, idx);
+          lua_settable(L, kf);
+          lua_remove(L, kf);
         }
       else
         {
@@ -1101,7 +1146,7 @@ LuaUnRegEvent(lua_State *L)
     }
   else
     {
-      LuaFreeHandler(&l->handler);
+      LuaFreeHandler(((struct lua_handler **)&(l->handler)));
       unregister_listener(l);
       lua_pushboolean(L, 1);
     }