From 9408dfc67c8c68e2cbaa9f0658a740af5e588e8c Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Thu, 27 Oct 2016 18:46:27 +0200 Subject: degesch: create Lua refs through introspection --- degesch.c | 175 +++++++++++++++++++++++++------------------------------------- 1 file changed, 71 insertions(+), 104 deletions(-) diff --git a/degesch.c b/degesch.c index 255bcff..0a76f6b 100644 --- a/degesch.c +++ b/degesch.c @@ -1252,9 +1252,9 @@ enum ispect_type ISPECT_UINT, ISPECT_SIZE, ISPECT_STRING, + ISPECT_REF, ///< Weakly referenced #if 0 // TODO: also str_map, str_vector - ISPECT_REF, ///< Weakly referenced ISPECT_LIST, ///< Typically copied, depending on type #endif }; @@ -1262,9 +1262,7 @@ enum ispect_type // TODO: once this finalizes, turn instatiations into macros struct ispect { - // TODO: - // - "list" flag? - // - weak_ref/weak_unref methods? + // TODO: "list" flag? struct ispect_field *fields; ///< Fields }; @@ -1280,7 +1278,7 @@ struct ispect_field { #field, offsetof (struct object, field), ISPECT_ ## type, NULL }, #define ISPECT_(object, field, type, subtype) \ { #field, offsetof (struct object, field), ISPECT_ ## type, \ - &g_ ## subtype ## _type }, + &g_ ## subtype ## _ispect }, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1588,13 +1586,17 @@ struct buffer struct user *user; ///< Reference to user }; +static struct ispect g_server_ispect; static struct ispect_field g_buffer_ispect_fields[] = { - ISPECT( buffer, name, STRING ) - ISPECT( buffer, new_messages_count, UINT ) - ISPECT( buffer, new_unimportant_count, UINT ) - ISPECT( buffer, highlighted, BOOL ) - ISPECT( buffer, hide_unimportant, BOOL ) + ISPECT ( buffer, name, STRING ) + ISPECT ( buffer, new_messages_count, UINT ) + ISPECT ( buffer, new_unimportant_count, UINT ) + ISPECT ( buffer, highlighted, BOOL ) + ISPECT ( buffer, hide_unimportant, BOOL ) + ISPECT_( buffer, server, REF, server ) + ISPECT_( buffer, channel, REF, channel ) + ISPECT_( buffer, user, REF, user ) {} }; @@ -1753,13 +1755,18 @@ struct server static struct ispect_field g_server_ispect_fields[] = { - ISPECT( server, name, STRING ) - ISPECT( server, state, INT ) - ISPECT( server, reconnect_attempt, UINT ) - ISPECT( server, manual_disconnect, BOOL ) - ISPECT( server, irc_user_host, STRING ) - ISPECT( server, autoaway_active, BOOL ) - ISPECT( server, cap_echo_message, BOOL ) + ISPECT ( server, name, STRING ) + ISPECT ( server, state, INT ) + ISPECT ( server, reconnect_attempt, UINT ) + ISPECT ( server, manual_disconnect, BOOL ) + ISPECT ( server, irc_user_host, STRING ) + ISPECT ( server, autoaway_active, BOOL ) + ISPECT ( server, cap_echo_message, BOOL ) + ISPECT_( server, buffer, REF, buffer ) + + // TODO: either rename the underlying field or fix the plugins + { "user", offsetof (struct server, irc_user), ISPECT_REF, &g_user_ispect }, + {} }; @@ -8521,8 +8528,6 @@ struct lua_weak_info const char *name; ///< Metatable name struct ispect *ispect; ///< Introspection data - // XXX: not sure if these should be _here_ and not in "struct ispect" - lua_weak_ref_fn ref; ///< Weak link invalidator lua_weak_unref_fn unref; ///< Weak link generator }; @@ -8683,33 +8688,6 @@ lua_buffer_gc (lua_State *L) return lua_weak_gc (L, &lua_buffer_info); } -static int -lua_buffer_get_user (lua_State *L) -{ - struct lua_weak *wrapper = lua_weak_deref (L, &lua_buffer_info); - struct buffer *buffer = wrapper->object; - lua_weak_push (wrapper->plugin, buffer->user, &lua_user_info); - return 1; -} - -static int -lua_buffer_get_channel (lua_State *L) -{ - struct lua_weak *wrapper = lua_weak_deref (L, &lua_buffer_info); - struct buffer *buffer = wrapper->object; - lua_weak_push (wrapper->plugin, buffer->channel, &lua_channel_info); - return 1; -} - -static int -lua_buffer_get_server (lua_State *L) -{ - struct lua_weak *wrapper = lua_weak_deref (L, &lua_buffer_info); - struct buffer *buffer = wrapper->object; - lua_weak_push (wrapper->plugin, buffer->server, &lua_server_info); - return 1; -} - static int lua_buffer_log (lua_State *L) { @@ -8734,9 +8712,6 @@ lua_buffer_execute (lua_State *L) static luaL_Reg lua_buffer_table[] = { { "__gc", lua_buffer_gc }, - { "get_user", lua_buffer_get_user }, - { "get_channel", lua_buffer_get_channel }, - { "get_server", lua_buffer_get_server }, { "log", lua_buffer_log }, { "execute", lua_buffer_execute }, { NULL, NULL } @@ -8750,24 +8725,6 @@ lua_server_gc (lua_State *L) return lua_weak_gc (L, &lua_server_info); } -static int -lua_server_get_user (lua_State *L) -{ - struct lua_weak *wrapper = lua_weak_deref (L, &lua_server_info); - struct server *server = wrapper->object; - lua_weak_push (wrapper->plugin, server->irc_user, &lua_user_info); - return 1; -} - -static int -lua_server_get_buffer (lua_State *L) -{ - struct lua_weak *wrapper = lua_weak_deref (L, &lua_server_info); - struct server *server = wrapper->object; - lua_weak_push (wrapper->plugin, server->buffer, &lua_buffer_info); - return 1; -} - static int lua_server_send (lua_State *L) { @@ -8780,8 +8737,6 @@ lua_server_send (lua_State *L) static luaL_Reg lua_server_table[] = { { "__gc", lua_server_gc }, - { "get_user", lua_server_get_user }, - { "get_buffer", lua_server_get_buffer }, { "send", lua_server_send }, { NULL, NULL } }; @@ -9794,7 +9749,10 @@ static struct lua_ispect_mapping } lua_types[] = { - { &g_buffer_ispect, &lua_buffer_info }, + { &g_user_ispect, &lua_user_info }, + { &g_channel_ispect, &lua_channel_info }, + { &g_buffer_ispect, &lua_buffer_info }, + { &g_server_ispect, &lua_server_info }, }; static void * @@ -9833,18 +9791,30 @@ lua_plugin_property_get_ispect (lua_State *L, const char *property_name) for (iter = info->ispect->fields; iter->name; iter++) if (!strcmp (property_name, iter->name)) break; + if (!iter->name) + return false; - if (iter->name) - { - void *p = (uint8_t *) weak->object + iter->offset; - switch (iter->type) - { - case ISPECT_BOOL: lua_pushboolean (L, *(bool *) p); return true; - case ISPECT_INT: lua_pushinteger (L, *(int *) p); return true; - case ISPECT_UINT: lua_pushinteger (L, *(unsigned *) p); return true; - case ISPECT_SIZE: lua_pushinteger (L, *(size_t *) p); return true; - case ISPECT_STRING: lua_pushstring (L, *(char **) p); return true; - } + void *p = (uint8_t *) weak->object + iter->offset; + switch (iter->type) + { + case ISPECT_BOOL: lua_pushboolean (L, *(bool *) p); return true; + case ISPECT_INT: lua_pushinteger (L, *(int *) p); return true; + case ISPECT_UINT: lua_pushinteger (L, *(unsigned *) p); return true; + case ISPECT_SIZE: lua_pushinteger (L, *(size_t *) p); return true; + case ISPECT_STRING: lua_pushstring (L, *(char **) p); return true; + case ISPECT_REF: + { + // TODO: we can definitely make a resolution table right in Lua, + // lua_plugin_reg_weak() can fill it automatically (lightud->lightud) + struct lua_weak_info *info = NULL; + for (size_t i = 0; i < N_ELEMENTS (lua_types); i++) + if (lua_types[i].ispect == iter->subtype) + { + info = lua_types[i].info; + lua_weak_push (weak->plugin, *(void **) p, info); + return true; + } + } } return false; } @@ -9910,13 +9880,10 @@ lua_plugin_property_set (lua_State *L) } static void -lua_plugin_create_meta (lua_State *L, const char *name, luaL_Reg *fns) +lua_plugin_reg_finish (lua_State *L, struct lua_weak_info *info) { - luaL_newmetatable (L, name); - luaL_setfuncs (L, fns, 0); - // Emulate properties for convenience - lua_pushlightuserdata (L, NULL); + lua_pushlightuserdata (L, info); lua_pushcclosure (L, lua_plugin_property_get, 1); lua_setfield (L, -2, "__index"); lua_pushcfunction (L, lua_plugin_property_set); @@ -9926,19 +9893,19 @@ lua_plugin_create_meta (lua_State *L, const char *name, luaL_Reg *fns) } static void -lua_plugin_create_weak (lua_State *L, struct lua_weak_info *info, luaL_Reg *fns) +lua_plugin_reg_meta (lua_State *L, const char *name, luaL_Reg *fns) { - luaL_newmetatable (L, info->name); + luaL_newmetatable (L, name); luaL_setfuncs (L, fns, 0); + lua_plugin_reg_finish (L, NULL); +} - // Emulate properties for convenience - lua_pushlightuserdata (L, info); - lua_pushcclosure (L, lua_plugin_property_get, 1); - lua_setfield (L, -2, "__index"); - lua_pushcfunction (L, lua_plugin_property_set); - lua_setfield (L, -2, "__newindex"); - - lua_pop (L, 1); +static void +lua_plugin_reg_weak (lua_State *L, struct lua_weak_info *info, luaL_Reg *fns) +{ + luaL_newmetatable (L, info->name); + luaL_setfuncs (L, fns, 0); + lua_plugin_reg_finish (L, info); } static struct plugin * @@ -9969,14 +9936,14 @@ lua_plugin_load (struct app_context *ctx, const char *filename, lua_setglobal (L, PROGRAM_NAME); // Create metatables for our objects - lua_plugin_create_meta (L, XLUA_HOOK_METATABLE, lua_hook_table); - lua_plugin_create_weak (L, &lua_user_info, lua_user_table); - lua_plugin_create_weak (L, &lua_channel_info, lua_channel_table); - lua_plugin_create_weak (L, &lua_buffer_info, lua_buffer_table); - lua_plugin_create_weak (L, &lua_server_info, lua_server_table); - lua_plugin_create_meta (L, XLUA_SCHEMA_METATABLE, lua_schema_table); - lua_plugin_create_meta (L, XLUA_CONNECTION_METATABLE, lua_connection_table); - lua_plugin_create_meta (L, XLUA_CONNECTOR_METATABLE, lua_connector_table); + lua_plugin_reg_meta (L, XLUA_HOOK_METATABLE, lua_hook_table); + lua_plugin_reg_weak (L, &lua_user_info, lua_user_table); + lua_plugin_reg_weak (L, &lua_channel_info, lua_channel_table); + lua_plugin_reg_weak (L, &lua_buffer_info, lua_buffer_table); + lua_plugin_reg_weak (L, &lua_server_info, lua_server_table); + lua_plugin_reg_meta (L, XLUA_SCHEMA_METATABLE, lua_schema_table); + lua_plugin_reg_meta (L, XLUA_CONNECTION_METATABLE, lua_connection_table); + lua_plugin_reg_meta (L, XLUA_CONNECTOR_METATABLE, lua_connector_table); struct error *error = NULL; if (luaL_loadfile (L, filename)) -- cgit v1.2.3-70-g09d2