# HG changeset patch # User Myhailo Danylenko # Date 1337484290 -10800 # Node ID 1be9411caf314ba5898eb8cf2881994ad0b15ac1 # Parent 2e5d5571a4ba04069610e12c34b55917bf70adf1 Add guards diff -r 2e5d5571a4ba -r 1be9411caf31 lua.c --- a/lua.c Sat May 19 23:44:25 2012 +0300 +++ b/lua.c Sun May 20 06:24:50 2012 +0300 @@ -1499,18 +1499,9 @@ lua_pop (L, 1); } -#if 0 // OPTION GUARDS -GSList *lua_installed_guards = NULL; - -typedef struct { - lua_State *L; // lua environment for handler use - int nameref; // reference to key name string - int cbref; // reference to guard function -// int objref; // self_reference to object - guint hid; // hook id for object destruction -} lua_guard_t; +#define MLUA_GUARD_REGISTRY "mcabber_guards" /// guard function /// Function to be called, when option changes it's value. @@ -1519,115 +1510,92 @@ /// R: string (value to save in hash table) static gchar *lua_guard_cb (const gchar *key, const gchar *value) { - lua_guard_t *cb = ;// FIXME - lua_State *L = cb -> L; + lua_State *L = lua; // FIXME - if (cb -> cbref == LUA_NOREF) - return g_strdup (value); - - lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> cbref); - if (!lua_isfunction (L, -1)) { - lua_pop (L, 1); - return g_strdup (value); + lua_getfield ( L, LUA_REGISTRYINDEX, MLUA_GUARD_REGISTRY ); // +1 + lua_getfield ( L, -1, key ); // +2 + if ( ! lua_isfunction ( L, -1 ) ) { + lua_pop ( L, 2 ); + return g_strdup ( value ); } - lua_pushstring (L, key); - lua_psuhstring (L, value); + lua_pushstring ( L, key ); // +3 + lua_pushstring ( L, value ); // +4 - if (lua_pcall (L, 2, 1, 0)) { - scr_log_print (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1)); - lua_pop (L, 1); - return g_strdup (value); + if ( lua_pcall ( L, 2, 1, 0 ) ) { // +2 + scr_log_print ( LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring ( L, -1 ) ); + lua_pop ( L, 2 ); + return g_strdup ( value ); + } else { + gchar *result = g_strdup ( lua_tostring ( L, -1 ) ); + lua_pop ( L, 2 ); + return result; } - - return g_strdup (lua_tostring (L, -1)); } -/// main.guard -/// Installs option guard for given option. Returns guard object, that -/// should be kept around as long, as guard is needed. -/// A: string (option name), guard function -/// R: userdata (guard object) -static int lua_main_guard (lua_State *L) +/// main.add_guard +/// Installs option guard for given option. +/// A: string ( option name ), guard function +/// R: boolean ( success ) +static int lua_main_add_guard ( lua_State *L ) { - const char *name = luaL_checkstring (L, 1); - int priority = G_PRIORITY_DEFAULT; - lua_guard_t *cb; + const char *name = luaL_checkstring ( L, 1 ); + luaL_argcheck ( L, lua_isfunction (L, 2), 2, "function expected" ); + lua_settop ( L, 2 ); - luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); - - cb = lua_newuserdata (L, sizeof (lua_guard_t)); - luaL_getmetatable (L, "mcabber.guard"); - lua_setmetatable (L, -2); - - lua_pushvalue (L, 1); - cb -> nameref = luaL_ref (L, LUA_REGISTRYINDEX); - lua_pushvalue (L, 2); - cb -> cbref = luaL_ref (L, LUA_REGISTRYINDEX); - cb -> L = L; - - settings_set_guard (name, lua_guard_cb) + if ( settings_set_guard ( name, lua_guard_cb ) ) { + lua_getfield ( L, LUA_REGISTRYINDEX, MLUA_GUARD_REGISTRY ); + lua_pushvalue ( L, 2 ); + lua_setfield ( L, 3, name ); + lua_pushboolean ( L, 1 ); + } else + lua_pushboolean ( L, 0 ); return 1; } -static void lua_mcabber_unregister_guard (lua_State *L, lua_guard_t *cb) -{ - const char *name; - - if (cb -> nameref == LUA_NOREF) - return; - - lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref); - name = lua_tostring (L, -1); - if (name) { - settings_del_guard (name); - luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref); - cb -> nameref = LUA_NOREF; - } - - lua_pop (L, 1); -} - -/// guard:del -/// Unregisters given option guard from mcabber. Object will be destroyed later. -static int lua_mcabber_guard_del (lua_State *L) +/// main.del_guard +/// Removes option guard from given option. +/// By default, lua will refuse to remove guards, not installed +/// by lua. Still, you can force guard removal. +/// A: string ( option name ), boolean ( force removal ) +/// R: boolean ( success ) +static int lua_main_del_guard ( lua_State *L ) { - lua_guard_t *cb = luaL_checkudata (L, 1, "mcabber.guard"); - luaL_argcheck (L, cb != NULL, 1, "mcabber guard object expected"); - lua_mcabber_unregister_guard (L, cb); - return 0; -} + const char *name = luaL_checkstring ( L, 1 ); + lua_settop ( L, 2 ); + + lua_getfield ( L, LUA_REGISTRYINDEX, MLUA_GUARD_REGISTRY ); + lua_getfield ( L, 3, name ); -static int lua_mcabber_guard_gc (lua_State *L) -{ - lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.guard"); - luaL_argcheck (L, cb != NULL, 1, "mcabber guard object expected"); - lua_mcabber_unregister_guard (L, cb); - if (cb -> cbref != LUA_NOREF) - luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref); - return 0; + if ( ! lua_isnil ( L, 4 ) || lua_toboolean ( L, 2 ) ) { + settings_del_guard ( name ); + lua_pushnil ( L ); + lua_setfield ( L, 3, name ); + lua_pushboolean ( L, 1 ); + } else + lua_pushboolean ( L, 0 ); + + return 1; } -static const luaL_Reg lua_mcabber_hook_reg_m[] = { - { "del", lua_mcabber_guard_del }, - { "__gc", lua_mcabber_guard_gc }, - { NULL, NULL }, -}; - static void lua_guard_init (lua_State *L) { - luaL_newmetatable (L, "mcabber.guard"); - lua_pushvalue (L, -1); - lua_setfield (L, -2, "__index"); - luaL_register (L, NULL, lua_mcabber_guard_reg_m); - lua_pop (L, 1); + lua_createtable ( L, 0, 0 ); + lua_setfield ( L, LUA_REGISTRYINDEX, MLUA_GUARD_REGISTRY ); } static void lua_guard_uninit (lua_State *L) { + lua_getfield ( L, LUA_REGISTRYINDEX, MLUA_GUARD_REGISTRY ); + lua_pushnil ( L ); + while ( lua_next ( L, -2 ) ) { + const char *key = lua_tostring ( L, -2 ); + settings_del_guard ( key ); + lua_pop ( L, 1 ); + } + lua_pop ( L, 1 ); } -#endif // MAIN INITIALIZATION CODE @@ -1719,6 +1687,8 @@ reg ( timer ) reg ( bgread ) reg ( hook ) + reg ( add_guard ) + reg ( del_guard ) { NULL, NULL }, }; #undef reg @@ -1776,6 +1746,7 @@ lua_hook_init (lua); lua_command_init (lua); + lua_guard_init (lua); { char *initfile = expand_filename (settings_opt_get ("lua_init_filename")); @@ -1803,7 +1774,7 @@ } } -static void lua_events_cancel (gpointer data, gpointer ignore) +static void lua_events_destroy ( gpointer data ) { lua_event_callback_t *cb = data; const char *evid; @@ -1812,38 +1783,29 @@ lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->evid); evid = lua_tostring (cb ->L, -1); evs_callback (evid, EVS_CONTEXT_CANCEL, "Module unloading"); + evs_del (evid); // XXX before these were two different runs. is there some reason for that? } -static void lua_events_destroy (gpointer data, gpointer ignore) +static void lua_bgreads_destroy ( gpointer data ) { - lua_event_callback_t *cb = data; - const char *evid; - if (cb->evid == LUA_NOREF) - return; - lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->evid); - evid = lua_tostring (cb ->L, -1); - evs_del (evid); + g_source_remove ( ( gulong ) data ); } -static void lua_bgreads_destroy (guint source, gpointer ignore) +static void lua_timers_destroy ( gpointer data ) { - g_source_remove (source); + g_source_remove ( ( gulong ) data ); } -static void lua_timers_destroy (guint source, gpointer ignore) +static void lua_features_destroy ( gpointer data ) { - g_source_remove (source); -} - -static void lua_features_destroy (char *xmlns, gpointer ignore) -{ + gchar *xmlns = data; xmpp_del_feature (xmlns); g_free (xmlns); } -static void lua_categories_destroy (guint id, gpointer ignore) +static void lua_categories_destroy ( gpointer data ) { - compl_del_category (id); + compl_del_category ( ( gulong ) data ); } void mlua_uninit (void) @@ -1856,23 +1818,17 @@ // hook handlers and commands will be unregistered upon objects destruction - g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL); - g_slist_free (lua_bgreads); + lua_guard_uninit ( lua ); + + g_slist_free_full ( lua_bgreads, lua_bgreads_destroy ); lua_bgreads = NULL; - g_slist_foreach (lua_timers, (GFunc) lua_timers_destroy, NULL); - g_slist_free (lua_timers); + g_slist_free_full ( lua_timers, lua_timers_destroy ); lua_timers = NULL; - g_slist_foreach (lua_events, (GFunc) lua_events_cancel, NULL); - g_slist_foreach (lua_events, (GFunc) lua_events_destroy, NULL); - g_slist_free (lua_events); + g_slist_free_full ( lua_events, lua_events_destroy ); lua_events = NULL; - g_slist_foreach (lua_added_features, (GFunc) lua_features_destroy, NULL); - g_slist_free (lua_added_features); - lua_added_features = NULL; - #ifdef MCABBER_API_HAVE_CMD_ID cmd_del (lua_cmdid); lua_cmdid = NULL; @@ -1883,8 +1839,10 @@ lua_close (lua); lua = NULL; - g_slist_foreach (lua_added_categories, (GFunc) lua_categories_destroy, NULL); - g_slist_free (lua_added_categories); + g_slist_free_full ( lua_added_features, lua_features_destroy ); + lua_added_features = NULL; + + g_slist_free_full ( lua_added_categories, lua_categories_destroy ); lua_added_categories = NULL; #ifdef LLM_LOG_HANDLER