/* GTK - The GIMP Toolkit * Copyright (C) 2014 Red Hat, Inc. * * 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 . */ #include "config.h" #include "reftest-module.h" struct _ReftestModule { int refcount; char *filename; GModule *module; }; static GHashTable *all_modules = NULL; static ReftestModule * reftest_module_find_existing (const char *filename) { if (all_modules == NULL) return NULL; return g_hash_table_lookup (all_modules, filename ? filename : ""); } static ReftestModule * reftest_module_new_take (GModule *module, char *filename) { ReftestModule *result; g_return_val_if_fail (module != NULL, NULL); result = g_slice_new0 (ReftestModule); result->refcount = 1; result->filename = filename; result->module = module; if (all_modules == NULL) all_modules = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (all_modules, filename ? filename : "", result); return result; } ReftestModule * reftest_module_new_self (void) { ReftestModule *result; GModule *module; result = reftest_module_find_existing (NULL); if (result) return reftest_module_ref (result); module = g_module_open (NULL, G_MODULE_BIND_LAZY); if (module == NULL) return NULL; return reftest_module_new_take (module, NULL); } ReftestModule * reftest_module_new (const char *directory, const char *module_name) { ReftestModule *result; char *full_path; GModule *module; g_return_val_if_fail (module_name != NULL, NULL); full_path = g_module_build_path (directory, module_name); result = reftest_module_find_existing (full_path); if (result) { g_free (full_path); return reftest_module_ref (result); } module = g_module_open (full_path, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY); if (module == NULL) { /* libtool hack */ char *libtool_dir = g_build_filename (directory, ".libs", NULL); g_free (full_path); full_path = g_module_build_path (libtool_dir, module_name); result = reftest_module_find_existing (full_path); if (result) { g_free (full_path); return reftest_module_ref (result); } module = g_module_open (full_path, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY); if (module == NULL) { g_free (full_path); return NULL; } } return reftest_module_new_take (module, full_path); } ReftestModule * reftest_module_ref (ReftestModule *module) { g_return_val_if_fail (module != NULL, NULL); module->refcount++; return module; } void reftest_module_unref (ReftestModule *module) { g_return_if_fail (module != NULL); module->refcount--; if (module->refcount > 0) return; if (!g_module_close (module->module)) { g_assert_not_reached (); } if (!g_hash_table_remove (all_modules, module->filename ? module->filename : "")) { g_assert_not_reached (); } g_free (module->filename); g_slice_free (ReftestModule, module); } GCallback reftest_module_lookup (ReftestModule *module, const char *function_name) { gpointer result; g_return_val_if_fail (module != NULL, NULL); g_return_val_if_fail (function_name != NULL, NULL); if (!g_module_symbol (module->module, function_name, &result)) return NULL; return result; }