From 83ecdcf791cb24410751cf9760b58df8d8d8a290 Mon Sep 17 00:00:00 2001 From: Rui Guo Date: Wed, 10 Jun 2009 22:02:18 +0800 Subject: [PATCH] Restructure the func register code. Now we have a unified Lua function registration mechanism. User can register with the function name, but the name is always resolved to the Lua function itself. Typo is detected at this stage. The Lua function is then mapped to a unique key, managed with reference counting. --- src/lua.c | 175 ++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 107 insertions(+), 68 deletions(-) diff --git a/src/lua.c b/src/lua.c index ac4c59f..1c07288 100644 --- a/src/lua.c +++ b/src/lua.c @@ -960,88 +960,127 @@ int LuaForeWindowChanged(void) return LuaCallProcess("fore_changed", params); } +int +LuaPushHTable(lua_State *L, int screen, const char * t) +{ + lua_pushstring(L, t); + lua_rawget(L, screen); + /* FIXME: Do we need to balance the stack here? */ + if (lua_isnil(L, -1)) + luaL_error(L, "Fatal! Fail to get function registeration table!"); + return lua_gettop(L); +} + +int +LuaFuncKey(lua_State *L, int idx) +{ + int key, funckey, sc; + luaL_getmetatable(L, "screen"); + sc = lua_gettop(L); + funckey = LuaPushHTable(L, sc, "_funckey"); + + lua_pushvalue(L, idx); + lua_gettable(L, funckey);/*funckey[func] ==?*/ + if (lua_isnil(L, -1)) + { + /* Not found, alloc a new key */ + + /*funckey[key] = 1*/ + lua_pushinteger(L, 1); + key = luaL_ref(L, funckey); + + /*funckey[func]=key*/ + lua_pushvalue(L, idx); + lua_pushinteger(L, key); + lua_settable(L, funckey); + + int keyfunc = LuaPushHTable(L, sc, "_keyfunc"); + /*keyfunc[key] = func*/ + lua_pushinteger(L, key); + lua_pushvalue(L, idx); + lua_settable(L, keyfunc); + + lua_pop(L, 1); + } + else + key = lua_tointeger(L, -1);/*key = funckey[func]*/ + + lua_pop(L, 3); + return key; +} + +void +LuaHRef(lua_State *L, int key, int reg) +{ + int funckey, keyfunc, cnt, sc, idx; + luaL_getmetatable(L, "screen"); + sc = lua_gettop(L); + funckey = LuaPushHTable(L, sc, "_funckey"); + keyfunc = LuaPushHTable(L, sc, "_keyfunc"); + + lua_rawgeti(L, keyfunc, key); + idx = lua_gettop(L); + + lua_rawgeti(L, funckey, key); + cnt = lua_tointeger(L, -1);/*cnt = htable[key]*/ + if (!reg && cnt <= 1) + { + /*release the last reference*/ + luaL_unref(L, funckey, key); + lua_pushvalue(L, idx); + lua_pushnil(L); + lua_settable(L, funckey); /*htable[func]=key*/ + } + else + { + lua_pushinteger(L, key); + lua_pushinteger(L, reg? cnt + 1 : cnt - 1); + lua_settable(L, funckey); /*htable[key] = cnt + 1*/ + } + lua_pop(L, 3); +} + +void +LuaHSetName(lua_State *L, int key, int name) +{ + int keyfunc, sc; + luaL_getmetatable(L, "screen"); + sc = lua_gettop(L); + keyfunc = LuaPushHTable(L, sc, "_keyfunc"); + + lua_rawgeti(L, keyfunc, key); + lua_pushvalue(L, name); + lua_rawset(L, keyfunc); + + lua_pop(L, 2); +} + struct lua_handler * LuaCheckHandler(lua_State *L, int idx, int reg) { + int name = 0, key, sc; if (lua_isstring(L, idx)) { const char * handler; /* registered with func name.*/ handler = luaL_checkstring(L, idx); + name = idx++; lua_getfield(L, LUA_GLOBALSINDEX, handler); if (!lua_isfunction(L, -1)) luaL_error(L, "The specified handler %s in param #%d is not a function", handler, idx); - lua_pop(L, 1); - return LuaAllocHandler(handler, 0); } - else if (lua_isfunction(L, idx)) - { - int key, htable; - if (idx < 0) - idx = lua_gettop(L) + 1 - idx; - - luaL_getmetatable(L, "screen"); - 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 */ - htable = lua_gettop(L); - lua_pushvalue(L, idx); - lua_gettable(L, htable);/*htable[func] ==?*/ - if (lua_isnil(L, -1)) - { - /* not found */ - int kf; - if (!reg) - { - 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 - { - int cnt; - key = lua_tointeger(L, -1);/*key = htable[func]*/ - lua_gettable(L, htable); - cnt = lua_tointeger(L, -1);/*cnt = htable[key]*/ - if (!reg && cnt <= 1) - { - /*release the last reference*/ - luaL_unref(L, htable, key); - lua_pushvalue(L, idx); - lua_pushnil(L); - lua_settable(L, htable); /*htable[func]=key*/ - } - else - { - lua_pushinteger(L, key); - lua_pushinteger(L, reg? cnt + 1 : cnt - 1); - lua_settable(L, htable); /*htable[key] = cnt + 1*/ - } - } + else if (!lua_isfunction(L, idx)) + luaL_error(L, "Handler should be a function or the name of function"); - lua_pop(L, 3); - return LuaAllocHandler(NULL, key); + sc = lua_gettop(L); + key = LuaFuncKey(L, idx ); + LuaHRef(L, key, reg); + if (name) + { + LuaHSetName(L, key, name); + lua_pop(L, 1); } - else - luaL_error(L, "Handler should be a function or the name of function"); - return NULL; + return LuaAllocHandler(NULL, key); } #define SEVNAME_MAX 30 -- 2.11.4.GIT