gplugin/gplugin

closing merged branch
draft bugfix/clang-format-tweaks
2020-07-14, Gary Kramlich
731607ef94c6
closing merged branch
/*
* Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "gplugin-tcc-loader.h"
#include <glib/gi18n-lib.h>
#include <libtcc.h>
#include "gplugin-tcc-plugin.h"
struct _GPluginTccLoader {
GPluginLoader parent;
};
G_DEFINE_DYNAMIC_TYPE(
GPluginTccLoader,
gplugin_tcc_loader,
GPLUGIN_TYPE_LOADER);
/******************************************************************************
* GPluginLoaderInterface API
*****************************************************************************/
static GSList *
gplugin_tcc_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l)
{
return g_list_append(NULL, "c");
}
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) {
g_set_error(
error,
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) {
g_set_error(
error,
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) {
g_set_error(
error,
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) {
g_set_error(
error,
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;
}
/* clang-format off */
plugin = g_object_new(
GPLUGIN_TCC_TYPE_PLUGIN,
"filename", filename,
"loader", loader,
"state", s,
"memory", memneeded,
"info", info,
NULL);
/* clang-format on */
return plugin;
}
static gboolean
gplugin_tcc_loader_load(
G_GNUC_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) {
g_set_error(error, GPLUGIN_DOMAIN, 0, "no gplugin_load function found");
return FALSE;
}
return gplugin_load(GPLUGIN_NATIVE_PLUGIN(plugin), error);
}
static gboolean
gplugin_tcc_loader_unload(
G_GNUC_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) {
g_set_error(
error,
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_init(G_GNUC_UNUSED GPluginTccLoader *loader)
{
}
static void
gplugin_tcc_loader_class_finalize(G_GNUC_UNUSED GPluginTccLoaderClass *klass)
{
}
static void
gplugin_tcc_loader_class_init(GPluginTccLoaderClass *klass)
{
GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass);
loader_class->supported_extensions =
gplugin_tcc_loader_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)
{
gplugin_tcc_loader_register_type(G_TYPE_MODULE(plugin));
}