gplugin/gplugin

0dcd20dd5e76
flow: Merged 'tcc-loader' to ('develop').
--- a/CMakeLists.txt Mon Aug 22 15:37:51 2016 -0500
+++ b/CMakeLists.txt Tue Aug 23 12:00:37 2016 -0500
@@ -195,6 +195,7 @@
add_subdirectory(lua)
add_subdirectory(perl)
add_subdirectory(python)
+add_subdirectory(tcc)
###############################################################################
# Install stuff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/Modules/FindLibTcc.cmake Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,51 @@
+find_path(libtcc_INCLUDE_DIR
+ NAMES libtcc.h
+ PATHS
+ /usr/include
+ /usr/local/include
+)
+
+# find home brew and stash the prefix of tcc if there is one
+set(BREW_TCC_PREFIX)
+if(APPLE)
+ find_program(BREW brew)
+ if(BREW)
+ execute_process(
+ COMMAND ${BREW} --prefix tcc
+ OUTPUT_VARIABLE BREW_TCC_PREFIX
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ set(BREW_TCC_LIB_DIR ${BREW_TCC_PREFIX}/lib)
+ set(BREW_TCC_INCLUDE_DIR ${BREW_TCC_PREFIX}/include)
+ endif(BREW)
+endif(APPLE)
+
+find_path(LIBTCC_INCLUDE_DIR
+ NAMES libtcc.h
+ PATHS
+ /usr/include
+ /usr/local/include
+ ${BREW_TCC_INCLUDE_DIR}
+)
+
+find_library(LIBTCC_LIBRARIES
+ NAMES libtcc.a
+ PATHS
+ /usr/lib
+ /usr/local/lib
+ /usr/lib/x86_64-linux-gnu
+ /usr/lib/x86_32-linux-gnu
+ ${BREW_TCC_LIB_DIR}
+)
+
+include(CMakeParseArguments)
+find_package_handle_standard_args(libtcc REQUIRED_VARS LIBTCC_LIBRARIES LIBTCC_INCLUDE_DIR)
+
+set(TCC_FOUND ${LIBTCC_FOUND})
+
+if(TCC_FOUND)
+ set(TCC_INCLUDE_DIRS ${LIBTCC_INCLUDE_DIR})
+ set(TCC_LIBRARIES ${LIBTCC_LIBRARY})
+endif(TCC_FOUND)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/CMakeLists.txt Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,39 @@
+option(
+ BUILD_TCC
+ "Whether or not to build the TCC plugin loader"
+ "Off"
+)
+
+if(BUILD_TCC)
+ set(GPLUGIN_TCC_SOURCES
+ gplugin-tcc-core.c
+ gplugin-tcc-loader.c
+ gplugin-tcc-plugin.c
+ )
+
+ set(GPLUGIN_TCC_HEADERS
+ gplugin-tcc-loader.h
+ gplugin-tcc-plugin.h
+ )
+
+ find_package(LibTcc REQUIRED)
+
+ include_directories(${LIBTCC_INCLUDE_DIR})
+
+ #pkg_check_modules(TCC REQUIRED libtcc)
+ add_library(gplugin-tcc MODULE
+ ${GPLUGIN_TCC_SOURCES}
+ ${GPLUGIN_TCC_HEADERS}
+ )
+ set_target_properties(gplugin-tcc PROPERTIES PREFIX "")
+
+ target_link_libraries(gplugin-tcc
+ ${LIBTCC_LIBRARIES}
+ gplugin
+ )
+
+ install(TARGETS gplugin-tcc DESTINATION lib/gplugin)
+endif(BUILD_TCC)
+
+add_subdirectory(tests)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/gplugin-tcc-core.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include "gplugin-tcc-loader.h"
+#include "gplugin-tcc-plugin.h"
+
+
+G_MODULE_EXPORT GPluginPluginInfo *
+gplugin_query(GPLUGIN_UNUSED GError **error) {
+ const gchar * const authors[] = {
+ "Eion Robb <eion@robbmob.com>",
+ NULL
+ };
+
+ return gplugin_plugin_info_new(
+ "gplugin/tcc-loader",
+ GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
+ "internal", TRUE,
+ "load-on-query", TRUE,
+ "name", "C source plugin loader",
+ "version", GPLUGIN_VERSION,
+ "license-id", "LGPL2",
+ "summary", "A plugin that can load C source plugins",
+ "description", "This plugin allows the loading of plugins written in C.",
+ "authors", authors,
+ "website", GPLUGIN_WEBSITE,
+ "category", "loaders",
+ NULL
+ );
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_load(GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ gplugin_tcc_loader_register(plugin);
+ gplugin_tcc_plugin_register(plugin);
+
+ gplugin_manager_register_loader(gplugin_tcc_loader_get_type());
+
+ return TRUE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return FALSE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/gplugin-tcc-loader.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gplugin-tcc-loader.h"
+
+#include "gplugin-tcc-plugin.h"
+
+#include <glib/gi18n.h>
+
+#include <libtcc.h>
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static GObjectClass *parent_class = NULL;
+static GType type_real = 0;
+
+/******************************************************************************
+ * GPluginLoaderInterface API
+ *****************************************************************************/
+static GSList *
+gplugin_tcc_loader_class_supported_extensions(GPLUGIN_UNUSED const GPluginLoaderClass *klass) {
+ GSList *exts = NULL;
+
+ exts = g_slist_append(exts, "c");
+
+ return exts;
+}
+
+static GPluginPlugin *
+gplugin_tcc_loader_query(GPluginLoader *loader, const gchar *filename,
+ GError **error)
+{
+ GPluginPlugin *plugin = NULL;
+ GPluginPluginInfo *info = NULL;
+ TCCState *s = NULL;
+ gpointer memneeded = NULL;
+ int memsize = -1;
+
+ GPluginTccPluginQueryFunc gplugin_query = NULL;
+
+ s = tcc_new();
+
+ tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+
+ if(tcc_add_file(s, filename) == -1) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "couldn't load file %s", filename);
+
+ tcc_delete(s);
+
+ return NULL;
+ }
+
+ /* copy code into memory */
+ if((memsize = tcc_relocate(s, NULL)) < 0) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "couldn't work out how much memory is needed");
+
+ tcc_delete(s);
+ return NULL;
+ }
+
+ memneeded = g_malloc0(memsize);
+ if(tcc_relocate(s, memneeded) < 0) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "could not relocate plugin into memory");
+
+ tcc_delete(s);
+ g_free(memneeded);
+ return NULL;
+ }
+
+ gplugin_query = (GPluginTccPluginQueryFunc) tcc_get_symbol(s, "gplugin_query");
+ if (gplugin_query == NULL) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "no gplugin_query function found");
+
+ tcc_delete(s);
+ g_free(memneeded);
+ return NULL;
+ }
+
+ info = gplugin_query(error);
+ if(info == NULL) {
+ tcc_delete(s);
+ g_free(memneeded);
+ return NULL;
+ }
+
+ plugin = g_object_new(GPLUGIN_TYPE_TCC_PLUGIN,
+ "filename", filename,
+ "loader", loader,
+ "state", s,
+ "memory", memneeded,
+ "info", info,
+ NULL);
+
+ return plugin;
+}
+
+static gboolean
+gplugin_tcc_loader_load(GPLUGIN_UNUSED GPluginLoader *loader,
+ GPluginPlugin *plugin,
+ GError **error)
+{
+ GPluginTccPluginLoadFunc gplugin_load = NULL;
+ TCCState *s = gplugin_tcc_plugin_get_state(GPLUGIN_TCC_PLUGIN(plugin));
+
+ gplugin_load = (GPluginTccPluginLoadFunc) tcc_get_symbol(s, "gplugin_load");
+ if (gplugin_load == NULL) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "no gplugin_load function found");
+
+ return FALSE;
+ }
+
+ return gplugin_load(GPLUGIN_NATIVE_PLUGIN(plugin), error);
+}
+
+static gboolean
+gplugin_tcc_loader_unload(GPLUGIN_UNUSED GPluginLoader *loader,
+ GPluginPlugin *plugin,
+ GError **error)
+{
+ GPluginTccPluginLoadFunc gplugin_unload = NULL;
+ TCCState *s = gplugin_tcc_plugin_get_state(GPLUGIN_TCC_PLUGIN(plugin));
+
+ gplugin_unload = (GPluginTccPluginUnloadFunc) tcc_get_symbol(s, "gplugin_unload");
+ if (gplugin_unload == NULL) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "no gplugin_unload function found");
+
+ return FALSE;
+ }
+
+ return gplugin_unload(GPLUGIN_NATIVE_PLUGIN(plugin), error);
+}
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+static void
+gplugin_tcc_loader_class_init(GPluginTccLoaderClass *klass) {
+ GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass);
+
+ parent_class = g_type_class_peek_parent(klass);
+
+ loader_class->supported_extensions =
+ gplugin_tcc_loader_class_supported_extensions;
+ loader_class->query = gplugin_tcc_loader_query;
+ loader_class->load = gplugin_tcc_loader_load;
+ loader_class->unload = gplugin_tcc_loader_unload;
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+void
+gplugin_tcc_loader_register(GPluginNativePlugin *plugin) {
+ if(g_once_init_enter(&type_real)) {
+ GType type = 0;
+
+ static const GTypeInfo info = {
+ .class_size = sizeof(GPluginTccLoaderClass),
+ .class_init = (GClassInitFunc)gplugin_tcc_loader_class_init,
+ .instance_size = sizeof(GPluginTccLoader),
+ };
+
+ type = gplugin_native_plugin_register_type(plugin,
+ GPLUGIN_TYPE_LOADER,
+ "GPluginTccLoader",
+ &info,
+ 0);
+
+ g_once_init_leave(&type_real, type);
+ }
+}
+
+GType
+gplugin_tcc_loader_get_type(void) {
+ if(G_UNLIKELY(type_real == 0)) {
+ g_warning("gplugin_tcc_loader_get_type was called before "
+ "the type was registered!\n");
+ }
+
+ return type_real;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/gplugin-tcc-loader.h Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GPLUGIN_TCC_LOADER_H
+#define GPLUGIN_TCC_LOADER_H
+
+#define GPLUGIN_TYPE_TCC_LOADER (gplugin_tcc_loader_get_type())
+#define GPLUGIN_TCC_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GPLUGIN_TYPE_TCC_LOADER, GPluginTccLoader))
+#define GPLUGIN_TCC_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), GPLUGIN_TYPE_TCC_LOADER, GPluginTccLoaderClass))
+#define GPLUGIN_IS_TCC_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GPLUGIN_TYPE_TCC_LOADER))
+#define GPLUGIN_IS_TCC_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), GPLUGIN_TYPE_TCC_LOADER))
+#define GPLUGIN_TCC_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GPLUGIN_TYPE_TCC_LOADER, GPluginTccLoaderClass))
+
+typedef struct _GPluginTccLoader GPluginTccLoader;
+typedef struct _GPluginTccLoaderClass GPluginTccLoaderClass;
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+struct _GPluginTccLoader {
+ GPluginLoader parent;
+
+ void (*_gplugin_reserved_1)(void);
+ void (*_gplugin_reserved_2)(void);
+ void (*_gplugin_reserved_3)(void);
+ void (*_gplugin_reserved_4)(void);
+};
+
+struct _GPluginTccLoaderClass {
+ GPluginLoaderClass parent;
+
+ void (*_gplugin_reserved_1)(void);
+ void (*_gplugin_reserved_2)(void);
+ void (*_gplugin_reserved_3)(void);
+ void (*_gplugin_reserved_4)(void);
+};
+
+G_BEGIN_DECLS
+
+void gplugin_tcc_loader_register(GPluginNativePlugin *plugin);
+GType gplugin_tcc_loader_get_type(void);
+
+G_END_DECLS
+
+#endif /* GPLUGIN_TCC_LOADER_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/gplugin-tcc-plugin.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gplugin-tcc-plugin.h"
+
+#include <libtcc.h>
+
+#define GPLUGIN_TCC_PLUGIN_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GPLUGIN_TYPE_TCC_PLUGIN, GPluginTccPluginPrivate))
+
+/******************************************************************************
+ * Typedefs
+ *****************************************************************************/
+typedef struct {
+ TCCState *s;
+ gpointer mem;
+} GPluginTccPluginPrivate;
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+ PROP_ZERO,
+ PROP_STATE,
+ PROP_MEM,
+ PROP_LAST,
+};
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static GObjectClass *parent_class = NULL;
+static GType type_real = 0;
+
+/******************************************************************************
+ * Private Stuff
+ *****************************************************************************/
+static void
+gplugin_tcc_plugin_set_state(GPluginTccPlugin *plugin, TCCState *s) {
+ GPluginTccPluginPrivate *priv = GPLUGIN_TCC_PLUGIN_GET_PRIVATE(plugin);
+
+ priv->s = s;
+}
+
+static void
+gplugin_tcc_plugin_set_memory(GPluginTccPlugin *plugin, gpointer mem) {
+ GPluginTccPluginPrivate *priv = GPLUGIN_TCC_PLUGIN_GET_PRIVATE(plugin);
+
+ priv->mem = mem;
+}
+
+/******************************************************************************
+ * Object Stuff
+ *****************************************************************************/
+static void
+gplugin_tcc_plugin_get_property(GObject *obj, guint param_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GPluginTccPlugin *plugin = GPLUGIN_TCC_PLUGIN(obj);
+
+ switch(param_id) {
+ case PROP_STATE:
+ g_value_set_pointer(value,
+ gplugin_tcc_plugin_get_state(plugin));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gplugin_tcc_plugin_set_property(GObject *obj, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GPluginTccPlugin *plugin = GPLUGIN_TCC_PLUGIN(obj);
+
+ switch(param_id) {
+ case PROP_STATE:
+ gplugin_tcc_plugin_set_state(plugin,
+ g_value_get_pointer(value));
+ break;
+ case PROP_MEM:
+ gplugin_tcc_plugin_set_memory(plugin,
+ g_value_get_pointer(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gplugin_tcc_plugin_finalize(GObject *obj) {
+ GPluginTccPluginPrivate *priv = GPLUGIN_TCC_PLUGIN_GET_PRIVATE(obj);
+
+ if(priv->s)
+ tcc_delete(priv->s);
+
+ if(priv->mem)
+ g_free(priv->mem);
+
+ G_OBJECT_CLASS(parent_class)->finalize(obj);
+}
+
+static void
+gplugin_tcc_plugin_class_init(GPluginTccPluginClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ parent_class = g_type_class_peek_parent(klass);
+
+ g_type_class_add_private(klass, sizeof(GPluginTccPluginPrivate));
+
+ obj_class->get_property = gplugin_tcc_plugin_get_property;
+ obj_class->set_property = gplugin_tcc_plugin_set_property;
+ obj_class->finalize = gplugin_tcc_plugin_finalize;
+
+ g_object_class_install_property(obj_class, PROP_STATE,
+ g_param_spec_pointer("state", "state",
+ "The TCC compilation context for the plugin",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property(obj_class, PROP_MEM,
+ g_param_spec_pointer("memory", "memory",
+ "The memory allocated for the symbol table for the plugin",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+void
+gplugin_tcc_plugin_register(GPluginNativePlugin *plugin) {
+ if(g_once_init_enter(&type_real)) {
+ GType type = 0;
+
+ static const GTypeInfo info = {
+ .class_size = sizeof(GPluginTccPluginClass),
+ .class_init = (GClassInitFunc)gplugin_tcc_plugin_class_init,
+ .instance_size = sizeof(GPluginTccPlugin),
+ };
+
+ type = gplugin_native_plugin_register_type(plugin,
+ GPLUGIN_TYPE_PLUGIN,
+ "GPluginTccPlugin",
+ &info,
+ 0);
+
+ g_once_init_leave(&type_real, type);
+ }
+}
+
+GType
+gplugin_tcc_plugin_get_type(void) {
+ if(G_UNLIKELY(type_real == 0)) {
+ g_warning("gplugin_tcc_plugin_get_type was called before "
+ "the type was registered!\n");
+ }
+
+ return type_real;
+}
+
+TCCState *
+gplugin_tcc_plugin_get_state(const GPluginTccPlugin *plugin) {
+ GPluginTccPluginPrivate *priv = GPLUGIN_TCC_PLUGIN_GET_PRIVATE(plugin);
+
+ return priv->s;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/gplugin-tcc-plugin.h Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GPLUGIN_TCC_PLUGIN_H
+#define GPLUGIN_TCC_PLUGIN_H
+
+#define GPLUGIN_TYPE_TCC_PLUGIN (gplugin_tcc_plugin_get_type())
+#define GPLUGIN_TCC_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GPLUGIN_TYPE_TCC_PLUGIN, GPluginTccPlugin))
+#define GPLUGIN_TCC_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), GPLUGIN_TYPE_TCC_PLUGIN, GPluginTccPluginClass))
+#define GPLUGIN_IS_TCC_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GPLUGIN_TYPE_TCC_PLUGIN))
+#define GPLUGIN_IS_TCC_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), GPLUGIN_TYPE_TCC_PLUGIN))
+#define GPLUGIN_TCC_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GPLUGIN_TYPE_TCC_PLUGIN, GPluginTccPluginClass))
+
+typedef struct _GPluginTccPlugin GPluginTccPlugin;
+typedef struct _GPluginTccPluginClass GPluginTccPluginClass;
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <libtcc.h>
+
+struct _GPluginTccPlugin {
+ GPluginPlugin parent;
+};
+
+struct _GPluginTccPluginClass {
+ GPluginPluginClass parent;
+
+ void (*_gplugin_reserved_1)(void);
+ void (*_gplugin_reserved_2)(void);
+ void (*_gplugin_reserved_3)(void);
+ void (*_gplugin_reserved_4)(void);
+};
+
+G_BEGIN_DECLS
+
+void gplugin_tcc_plugin_register(GPluginNativePlugin *plugin);
+GType gplugin_tcc_plugin_get_type(void);
+
+TCCState *gplugin_tcc_plugin_get_state(const GPluginTccPlugin *plugin);
+
+typedef GPluginPluginInfo *(*GPluginTccPluginQueryFunc)(GError **error);
+typedef gboolean (*GPluginTccPluginLoadFunc)(GPluginNativePlugin *plugin, GError **error);
+typedef gboolean (*GPluginTccPluginUnloadFunc)(GPluginNativePlugin *plugin, GError **error);
+
+G_END_DECLS
+
+#endif /* GPLUGIN_TCC_PLUGIN_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/CMakeLists.txt Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,52 @@
+if(BUILD_TCC)
+
+macro(add_tcc_gtest target)
+ add_executable(${target} ${target}.c)
+ target_link_libraries(${target}
+ ${GLIB_LIBRARIES} ${TCC_LIBRARIES} gplugin
+ )
+ add_dependencies(${target} gplugin-tcc)
+
+ get_target_property(_output_name ${target} RUNTIME_OUTPUT_NAME)
+ if(NOT ${_output_name})
+ get_target_property(_output_name ${target} LOCATION)
+ endif(NOT ${_output_name})
+
+ list(APPEND TCC_TESTS ${_output_name})
+endmacro(add_tcc_gtest)
+
+add_definitions(
+ -DTCC_LOADER_DIR="${CMAKE_BINARY_DIR}/tcc"
+ -DTCC_PLUGIN_DIR="${CMAKE_CURRENT_SOURCE_DIR}/plugins"
+)
+
+add_tcc_gtest(test-tcc-loader)
+target_link_libraries(test-tcc-loader gplugin-loader-tests)
+
+set(GTESTER_TCC_TESTS "${TCC_TESTS}")
+set(GTESTER_TCC_LOG "test-gplugin-tcc.xml")
+set(GTESTER_TCC_JUNIT "test-gplugin-tcc-junit.xml")
+
+add_custom_command(
+ COMMAND ${GTESTER} -k --verbose -o ${GTESTER_TCC_LOG} ${TCC_TESTS}
+ OUTPUT ${GTESTER_TCC_LOG}
+ DEPENDS gplugin ${GPLUGIN_GIR_TARGETS} gplugin-tcc
+ ${TCC_TESTS} ${CMAKE_CURRENT_SOURCE_DIR}/plugins
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+add_custom_command(
+ COMMAND ${XSLTPROC} -o ${GTESTER_TCC_JUNIT} --nonet
+ ${CMAKE_SOURCE_DIR}/xsl/gtester-junit.xsl
+ ${GTESTER_TCC_LOG}
+ OUTPUT ${GTESTER_TCC_JUNIT}
+ DEPENDS ${GTESTER_TCC_LOG}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+add_custom_target(tcc-tests ALL
+ DEPENDS ${GTESTER_TCC_LOG} ${GTESTER_TCC_JUNIT} ${TCC_TESTS}
+)
+
+endif(BUILD_TCC)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/plugins/basic-plugin.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+G_MODULE_EXPORT GPluginPluginInfo *
+gplugin_query(GPLUGIN_UNUSED GError **error) {
+ const gchar * const authors[] = {
+ "author1",
+ NULL
+ };
+
+ return gplugin_plugin_info_new(
+ "gplugin/native-basic-plugin",
+ 0x01020304,
+ "name", "basic plugin",
+ "category", "test",
+ "version", "version",
+ "summary", "summary",
+ "license-id", "license",
+ "description", "description",
+ "authors", authors,
+ "website", "website",
+ NULL
+ );
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_load(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/plugins/dependent.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+G_MODULE_EXPORT GPluginPluginInfo *
+gplugin_query(GPLUGIN_UNUSED GError **error) {
+ const gchar * const dependencies[] = {
+ "dependency1",
+ "dependency2",
+ NULL
+ };
+
+ return gplugin_plugin_info_new(
+ "gplugin/native-dependent-plugin",
+ GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
+ "dependencies", dependencies,
+ NULL
+ );
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_load(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/plugins/load-exception.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+G_MODULE_EXPORT GPluginPluginInfo *
+gplugin_query(GPLUGIN_UNUSED GError **error) {
+ return gplugin_plugin_info_new(
+ "gplugin/native-load-exception",
+ GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
+ NULL
+ );
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_load(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return FALSE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/plugins/load-failed.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+G_MODULE_EXPORT GPluginPluginInfo *
+gplugin_query(GPLUGIN_UNUSED GError **error) {
+ return gplugin_plugin_info_new(
+ "gplugin/native-load-failed",
+ GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
+ NULL
+ );
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_load(GPLUGIN_UNUSED GPluginNativePlugin *plugin, GError **error) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "expected error");
+
+ return FALSE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/plugins/unload-failed.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+G_MODULE_EXPORT GPluginPluginInfo *
+gplugin_query(GPLUGIN_UNUSED GError **error) {
+ return gplugin_plugin_info_new(
+ "gplugin/native-unload-failed",
+ GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
+ NULL
+ );
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_load(GPLUGIN_UNUSED GPluginNativePlugin *plugin,
+ GPLUGIN_UNUSED GError **error)
+{
+ return TRUE;
+}
+
+G_MODULE_EXPORT gboolean
+gplugin_unload(GPLUGIN_UNUSED GPluginNativePlugin *plugin, GError **error) {
+ if(error)
+ *error = g_error_new(GPLUGIN_DOMAIN, 0, "expected error");
+
+ return FALSE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcc/tests/test-tcc-loader.c Tue Aug 23 12:00:37 2016 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011-2013 Gary Kramlich <grim@reaperworld.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <gplugin.h>
+
+#include <gplugin/gplugin-loader-tests.h>
+
+gint
+main(gint argc, gchar **argv) {
+ g_test_init(&argc, &argv, NULL);
+
+ gplugin_loader_tests_main(TCC_LOADER_DIR, TCC_PLUGIN_DIR, "c");
+
+ return g_test_run();
+}
+