diff options
Diffstat (limited to 'loaders/lua5.1/peas-plugin-loader-lua.c')
-rw-r--r-- | loaders/lua5.1/peas-plugin-loader-lua.c | 297 |
1 files changed, 55 insertions, 242 deletions
diff --git a/loaders/lua5.1/peas-plugin-loader-lua.c b/loaders/lua5.1/peas-plugin-loader-lua.c index d477ecb..32c6418 100644 --- a/loaders/lua5.1/peas-plugin-loader-lua.c +++ b/loaders/lua5.1/peas-plugin-loader-lua.c @@ -2,7 +2,7 @@ * peas-plugin-loader-lua.c * This file is part of libpeas * - * Copyright (C) 2014 - Garrett Regier + * Copyright (C) 2014-2015 - Garrett Regier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published by @@ -32,6 +32,7 @@ #include <lauxlib.h> #include <lualib.h> +#include "peas-lua-internal.h" #include "peas-lua-utils.h" @@ -64,173 +65,6 @@ peas_register_types (PeasObjectModule *module) PEAS_TYPE_PLUGIN_LOADER_LUA); } -static gboolean -_lua_add_package_path (lua_State *L, - const gchar *package_path) -{ - luaL_checkstack (L, 3, ""); - - lua_getglobal (L, "package"); - lua_getfield (L, -1, "path"); - - if (!lua_isstring (L, -1)) - { - g_warning ("Invalid Lua package.path: %s", lua_tostring (L, -1)); - - /* Pop path and package */ - lua_pop (L, 2); - return FALSE; - } - - /* ";package_path/?.lua;package_path/?/init.lua" */ - lua_pushliteral (L, ";"); - lua_pushstring (L, package_path); - lua_pushliteral (L, G_DIR_SEPARATOR_S "?.lua;"); - lua_pushstring (L, package_path); - lua_pushliteral (L, G_DIR_SEPARATOR_S "?" G_DIR_SEPARATOR_S "init.lua"); - lua_concat (L, 5); - - if (strstr (lua_tostring (L, -2), lua_tostring (L, -1)) != NULL) - { - /* Pop new path and path */ - lua_pop (L, 2); - } - else - { - /* Update package.path */ - lua_concat (L, 2); - lua_setfield (L, -2, "path"); - } - - /* Pop package */ - lua_pop (L, 1); - return TRUE; -} - -static gboolean -_lua_has_package (lua_State *L, - const gchar *package_name) -{ - gboolean has_package; - - luaL_checkstack (L, 3, ""); - - lua_getglobal (L, "package"); - lua_getfield (L, -1, "loaded"); - lua_getfield (L, -1, package_name); - - has_package = !lua_isnil (L, -1); - - /* Pop package, loaded and package's table */ - lua_pop (L, 3); - return has_package; -} - -static gboolean -_lua_pushinstance (lua_State *L, - const gchar *namespace_, - const gchar *name, - GType gtype, - gpointer instance) -{ - luaL_checkstack (L, 3, ""); - - if (!peas_lua_utils_require (L, "lgi")) - return FALSE; - - lua_getfield (L, -1, namespace_); - lua_getfield (L, -1, name); - - /* Remove the namespace and lgi's module table */ - lua_replace (L, -2); - lua_replace (L, -2); - - lua_pushlightuserdata (L, instance); - lua_pushboolean (L, FALSE); - - /* new(addr[, already_own[, no_sink]]) */ - if (lua_pcall (L, 2, 1, 0) != 0) - { - g_warning ("Failed to create Lua object of type '%s': %s", - g_type_name (gtype), lua_tostring (L, -1)); - - /* Pop the error */ - lua_pop (L, 1); - return FALSE; - } - - /* Check that the Lua object was created correctly */ - lua_getfield (L, -1, "_native"); - g_assert (lua_islightuserdata (L, -1)); - g_assert (lua_touserdata (L, -1) == instance); - lua_pop (L, 1); - - return TRUE; -} - -static GType -_lua_get_gtype (lua_State *L, - int index) -{ - GType gtype = G_TYPE_INVALID; - - luaL_checkstack (L, 1, ""); - - lua_getfield (L, index, "_gtype"); - - if (lua_type (L, -1) == LUA_TLIGHTUSERDATA) - gtype = (GType) lua_touserdata (L, -1); - - /* Pop _gtype */ - lua_pop (L, 1); - return gtype; -} - -static GType -_lua_find_extension_type (lua_State *L, - PeasPluginInfo *info, - GType exten_type) -{ - GType found_type = G_TYPE_INVALID; - - luaL_checkstack (L, 3, ""); - - /* Get the module's table */ - lua_pushstring (L, info->filename); - lua_rawget (L, LUA_REGISTRYINDEX); - - /* Must always have a valid key */ - lua_pushnil (L); - while (lua_next (L, -2) != 0) - { - if (lua_istable (L, -1)) - { - found_type = _lua_get_gtype (L, -1); - - if (found_type != G_TYPE_INVALID) - { - if (!g_type_is_a (found_type, exten_type)) - { - found_type = G_TYPE_INVALID; - } - else - { - /* Pop value and key */ - lua_pop (L, 2); - break; - } - } - } - - /* Pop the value but keep the key for the next iteration */ - lua_pop (L, 1); - } - - /* Pop the module's table */ - lua_pop (L, 1); - return found_type; -} - static lua_State * thread_enter (PeasPluginLoaderLua *lua_loader, PeasPluginInfo *info) @@ -277,6 +111,33 @@ thread_leave (PeasPluginLoaderLua *lua_loader, priv->lgi_leave_func (priv->lgi_lock); } +static GType +find_lua_extension_type (lua_State *L, + PeasPluginInfo *info, + GType exten_type) +{ + luaL_checkstack (L, 2, ""); + lua_pushstring (L, info->filename); + lua_pushlightuserdata (L, GSIZE_TO_POINTER (exten_type)); + + if (peas_lua_internal_call (L, "find_extension_type", + 2, LUA_TLIGHTUSERDATA)) + { + GType extension_type; + + extension_type = (GType) lua_touserdata (L, -1); + lua_pop (L, 1); + + if (g_type_is_a (extension_type, exten_type)) + return extension_type; + + g_warning ("Found invalid extension type '%s' for '%s'", + g_type_name (extension_type), g_type_name (exten_type)); + } + + return G_TYPE_INVALID; +} + static gboolean peas_plugin_loader_lua_provides_extension (PeasPluginLoader *loader, PeasPluginInfo *info, @@ -284,14 +145,14 @@ peas_plugin_loader_lua_provides_extension (PeasPluginLoader *loader, { PeasPluginLoaderLua *lua_loader = PEAS_PLUGIN_LOADER_LUA (loader); lua_State *L; - GType extension_type; + GType the_type; L = thread_enter (lua_loader, info); - extension_type = _lua_find_extension_type (L, info, exten_type); + the_type = find_lua_extension_type (L, info, exten_type); thread_leave (lua_loader, info, &L); - return extension_type != G_TYPE_INVALID; + return the_type != G_TYPE_INVALID; } static PeasExtension * @@ -308,16 +169,10 @@ peas_plugin_loader_lua_create_extension (PeasPluginLoader *loader, L = thread_enter (lua_loader, info); - the_type = _lua_find_extension_type (L, info, exten_type); + the_type = find_lua_extension_type (L, info, exten_type); if (the_type == G_TYPE_INVALID) goto out; - if (!g_type_is_a (the_type, exten_type)) - { - g_warn_if_fail (g_type_is_a (the_type, exten_type)); - goto out; - } - object = g_object_newv (the_type, n_parameters, parameters); if (object == NULL) goto out; @@ -328,29 +183,12 @@ peas_plugin_loader_lua_create_extension (PeasPluginLoader *loader, g_object_set_qdata (object, extension_type_quark (), GSIZE_TO_POINTER (exten_type)); - luaL_checkstack (L, 3, ""); - - if (!_lua_pushinstance (L, "GObject", "Object", the_type, object)) - { - g_clear_object (&object); - goto out; - } - - lua_getfield (L, -1, "priv"); - - if (!_lua_pushinstance (L, "Peas", "PluginInfo", - PEAS_TYPE_PLUGIN_INFO, info)) - { - g_clear_object (&object); - } - else - { - /* Set the plugin info as self.priv.plugin_info */ - lua_setfield (L, -2, "plugin_info"); - } + luaL_checkstack (L, 2, ""); + lua_pushlightuserdata (L, object); + lua_pushlightuserdata (L, info); - /* Pop priv and object */ - lua_pop (L, 2); + if (!peas_lua_internal_call (L, "setup_extension", 2, LUA_TNIL)) + g_clear_object (&object); out: @@ -364,53 +202,21 @@ peas_plugin_loader_lua_load (PeasPluginLoader *loader, { PeasPluginLoaderLua *lua_loader = PEAS_PLUGIN_LOADER_LUA (loader); lua_State *L; - gboolean success; + gboolean success = FALSE; L = thread_enter (lua_loader, info); - luaL_checkstack (L, 2, ""); - - /* Get the module's table */ + luaL_checkstack (L, 3, ""); lua_pushstring (L, info->filename); - lua_rawget (L, LUA_REGISTRYINDEX); + lua_pushstring (L, peas_plugin_info_get_module_dir (info)); + lua_pushstring (L, peas_plugin_info_get_module_name (info)); - if (!lua_isnil (L, -1)) - { - success = lua_istable (L, -1); - } - else + if (peas_lua_internal_call (L, "load", 3, LUA_TBOOLEAN)) { - const gchar *module_dir, *module_name; - - module_dir = peas_plugin_info_get_module_dir (info); - module_name = peas_plugin_info_get_module_name (info); - - /* Must push the key back onto the stack */ - lua_pushstring (L, info->filename); - - /* Push something that isn't a table */ - lua_pushboolean (L, FALSE); - - if (_lua_has_package (L, module_name)) - { - g_warning ("Error loading plugin '%s': " - "module name '%s' has already been used", - info->filename, module_name); - } - else if (_lua_add_package_path (L, module_dir) && - peas_lua_utils_require (L, module_name)) - { - /* Remove the boolean */ - lua_replace (L, -2); - } - - success = lua_istable (L, -1); - lua_rawset (L, LUA_REGISTRYINDEX); + success = lua_toboolean (L, -1); + lua_pop (L, 1); } - /* Pop the module's table */ - lua_pop (L, 1); - thread_leave (lua_loader, info, &L); return success; } @@ -433,9 +239,9 @@ peas_plugin_loader_lua_unload (PeasPluginLoader *loader, lua_pushnil (L); lua_rawset (L, LUA_REGISTRYINDEX); - priv->lgi_leave_func (priv->lgi_lock); - info->loader_data = NULL; + + priv->lgi_leave_func (priv->lgi_lock); } static void @@ -447,7 +253,7 @@ peas_plugin_loader_lua_garbage_collect (PeasPluginLoader *loader) priv->lgi_enter_func (priv->lgi_lock); - lua_gc (L, LUA_GCCOLLECT, 0); + peas_lua_internal_call (L, "garbage_collect", 0, LUA_TNIL); priv->lgi_leave_func (priv->lgi_lock); } @@ -515,6 +321,12 @@ peas_plugin_loader_lua_initialize (PeasPluginLoader *loader) /* Pop lgi's module table */ lua_pop (L, 1); + if (!peas_lua_internal_setup (L)) + { + /* Already warned */ + return FALSE; + } + /* Assert that no values were leaked to the stack */ g_assert_cmpint (lua_gettop (L), ==, 0); @@ -548,6 +360,7 @@ peas_plugin_loader_lua_finalize (GObject *object) if (priv->lgi_enter_func != NULL) priv->lgi_enter_func (priv->lgi_lock); + peas_lua_internal_shutdown (priv->L); g_clear_pointer (&priv->L, (GDestroyNotify) lua_close); G_OBJECT_CLASS (peas_plugin_loader_lua_parent_class)->finalize (object); |