diff --git a/degesch.c b/degesch.c index b66114b..5d1186c 100644 --- a/degesch.c +++ b/degesch.c @@ -8173,8 +8173,38 @@ lua_plugin_property_get (lua_State *L) return 1; } - return luaL_error (L, "%s: %s", - "no such method or property", property_name); + // Or we look for a property set by the user (__gc cannot be overriden) + if (lua_getuservalue (L, 1) != LUA_TTABLE) + lua_pushnil (L); + else + lua_getfield (L, -1, property_name); + return 1; +} + +static int +lua_plugin_property_set (lua_State *L) +{ + luaL_checktype (L, 1, LUA_TUSERDATA); + const char *property_name = luaL_checkstring (L, 2); + luaL_checkany (L, 3); + + // We use the associated value to store user-defined properties + int type = lua_getuservalue (L, 1); + if (type == LUA_TNIL) + { + lua_pop (L, 1); + lua_newtable (L); + lua_pushvalue (L, -1); + lua_setuservalue (L, 1); + } + else if (type != LUA_TTABLE) + return luaL_error (L, "associated value is not a table"); + + // Beware that we do not check for conflicts here; + // if Lua code writes a conflicting field, it is effectively ignored + lua_pushvalue (L, 3); + lua_setfield (L, -2, property_name); + return 0; } static void @@ -8186,6 +8216,9 @@ lua_plugin_create_meta (lua_State *L, const char *name, luaL_Reg *fns) // Emulate properties for convenience lua_pushcfunction (L, lua_plugin_property_get); lua_setfield (L, -2, "__index"); + lua_pushcfunction (L, lua_plugin_property_set); + lua_setfield (L, -2, "__newindex"); + lua_pop (L, 1); }