From: Rui Guo Date: Wed, 10 Jun 2009 07:42:55 +0000 (+0800) Subject: Merge branch 'lua-scripting' into screen-scripting-soc X-Git-Url: https://repo.or.cz/w/screen-lua.git/commitdiff_plain/6ee699f2e4d424e98731efc2e35162eeba64b03a Merge branch 'lua-scripting' into screen-scripting-soc With some local modifications. Still not work. --- 6ee699f2e4d424e98731efc2e35162eeba64b03a diff --cc src/lua.c index 33e1142,161b47e..5f607b6 --- a/src/lua.c +++ b/src/lua.c @@@ -78,8 -78,23 +78,54 @@@ extern struct layer *flayer static int LuaDispatch(void *handler, const char *params, va_list va); static int LuaRegEvent(lua_State *L); static int LuaUnRegEvent(lua_State *L); +static void LuaShowErr(lua_State *L); + enum + { + LUA_HANDLER_TYPE_N = 1, + LUA_HANDLER_TYPE_F + }; + + struct lua_handler + { + int type; + union + { - char *name; ++ const char *name; + int reference; + } u; + }; + ++struct lua_handler * ++LuaAllocHandler(const char *name, int ref) ++{ ++ struct lua_handler *lh; ++ lh = (struct lua_handler*) malloc(sizeof(struct lua_handler)); ++ if (!lh) ++ return NULL; ++ ++ if (name) ++ { ++ lh->type = LUA_HANDLER_TYPE_N; ++ lh->u.name = name; ++ } ++ else ++ { ++ lh->type = LUA_HANDLER_TYPE_F; ++ lh->u.reference = ref; ++ } ++ ++ return lh; ++} ++ ++void ++LuaFreeHandler(struct lua_handler **lh) ++{ ++ if ((*lh)->type == LUA_HANDLER_TYPE_N) ++ Free((*lh)->u.name); ++ Free(*lh); ++} ++ /** Template {{{ */ #define CHECK_TYPE(name, type) \ @@@ -878,77 -864,19 +928,76 @@@ int LuaForeWindowChanged(void return LuaCallProcess("fore_changed", params); } - char * -/* -int -LuaCommandExecuted(const char *command, const char **args, int argc) ++struct lua_handler * +LuaCheckHandler(lua_State *L, int idx, int reg) { - if (!L) - return 0; - struct fn_def params[] = { - {lua_pushstring, command}, - {push_stringarray, args}, - {NULL, NULL} - }; - return LuaCallProcess("command_executed", params); -}*/ + if (lua_isstring(L, idx)) + { + const char * handler; + /* registered with func name.*/ + handler = luaL_checkstring(L, 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 SaveStr(handler); ++ return LuaAllocHandler(handler, 0); + } + 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_rawget(L, -2); + 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 */ + if (!reg) + return NULL; + 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*/ + } + 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*/ + } + } + + lua_pop(L, 3); - snprintf(buf, 20, "%d", key); - return SaveStr(buf); ++ return LuaAllocHandler(NULL, key); + } + else + luaL_error(L, "Handler should be a function or the name of function"); + return NULL; +} #define SEVNAME_MAX 30 static int @@@ -958,7 -886,8 +1007,8 @@@ LuaRegEvent(lua_State *L * or: hook(event, handler, priv) * returns: A ticket for later unregister. */ int idx = 1, argc = lua_gettop(L); - int priv = 31; /* Default privilege */ - struct lua_handler lh; + unsigned int priv = 31; /* Default privilege */ ++ struct lua_handler *lh; char *obj = NULL; const char *objname = "global"; @@@ -985,8 -914,18 +1035,10 @@@ event = luaL_checkstring(L, idx++); snprintf(evbuf, SEVNAME_MAX, "%s_%s", objname, event); - if (lua_isfunction(L, idx)) - { - lua_pushvalue(L, idx); - lh.u.reference = luaL_ref(L, LUA_REGISTRYINDEX); - lh.type = LUA_HANDLER_TYPE_F; - idx++; - } - else - { - lh.type = LUA_HANDLER_TYPE_N; - lh.u.name = SaveStr(luaL_checkstring(L, idx++)); - } + /* Check and get the handler */ - handler = LuaCheckHandler(L, idx++, 1); ++ lh = LuaCheckHandler(L, idx++, 1); ++ if (!lh) ++ luaL_error(L, "Out of memory"); StackDump(L, "In RegEvent\n"); @@@ -1000,15 -939,20 +1052,18 @@@ l = (struct listener *)malloc(sizeof(struct listener)); if (!l) return luaL_error(L, "Out of memory"); - l->handler = (void *)handler; - l->handler = &lh; l->priv = priv; l->dispatcher = LuaDispatch; if (register_listener(sev, l)) { free(l); - return luaL_error(L, "Handler %s has already been registered", handler); - if (lh.type == LUA_HANDLER_TYPE_N) - return luaL_error(L, "Handler %s has already been registered", lh.u.name); ++ if (lh->type == LUA_HANDLER_TYPE_N) ++ return luaL_error(L, "Handler %s has already been registered", lh->u.name); + else + return luaL_error(L, "Handler has already been registered"); } - /*Return the handler for un-register*/ + /* Return the handler for un-register */ - l->handler = malloc(sizeof(struct lua_handler)); - memcpy(l->handler, &lh, sizeof(struct lua_handler)); ++ l->handler = lh; lua_pushlightuserdata(L, l); } else @@@ -1050,7 -990,10 +1101,7 @@@ LuaUnRegEvent(lua_State *L } else { - free(l->handler); - struct lua_handler *lh = l->handler; - if (lh->type == LUA_HANDLER_TYPE_N) - Free(lh->u.name); - Free(l->handler); ++ LuaFreeHandler(&l->handler); unregister_listener(l); lua_pushboolean(L, 1); }