diff --git a/ChangeLog b/ChangeLog index 05e220563..3e2ce7884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 05e220563..3e2ce7884 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * configure.in: Determine the suffix of the shared librarries for + this system. This is done analogous to + ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either + "sl", "dll", or (most often) "so". + + * tests/Makefile.am, tests/module-test.c, + tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c: + Added new testcase for gmodule. This is mostly copied from + gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are + some tests that verbose, not to say loquacious...) + 2000-12-19 Sebastian Wilhelmi * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/configure.in b/configure.in index 0eec822d3..b0174ee68 100644 --- a/configure.in +++ b/configure.in @@ -680,6 +680,21 @@ dnl *** done, have e got an implementation? if test -z "$G_MODULE_IMPL"; then G_MODULE_IMPL=0 fi + +AC_MSG_CHECKING(for the suffix of shared libraries) +case "$host_os" in + hpux9* | hpux10* | hpux11*) # taken from ltconfig + glib_gmodule_suffix='sl' + ;; + cygwin* | mingw*) + glib_gmodule_suffix='dll' + ;; + *) + glib_gmodule_suffix='so' + ;; +esac +AC_MSG_RESULT(.$glib_gmodule_suffix) + AC_SUBST(G_MODULE_IMPL) AC_SUBST(G_MODULE_LIBS) AC_SUBST(G_MODULE_LIBS_EXTRA) @@ -1499,6 +1514,8 @@ _______EOF cat >>$outfile <<_______EOF +#define G_MODULE_SUFFIX "$g_module_suffix" + G_END_DECLS #endif /* GLIBCONFIG_H */ @@ -1709,6 +1726,8 @@ g_mutex_sizeof="$glib_cv_sizeof_gmutex" g_system_thread_sizeof="$glib_cv_sizeof_system_thread" g_mutex_contents="$glib_cv_byte_contents_gmutex" +g_module_suffix="$glib_gmodule_suffix" + case $host in *-*-beos*) glib_os="#define G_OS_BEOS" diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index c24794f73..92634cf2f 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,9 @@ +2000-12-22 Sebastian Wilhelmi + + * glib/glib-sections.txt: Added G_MODULE_SUFFIX. + + * glib/tmpl/modules.sgml: Updated. + 2000-12-19 Sebastian Wilhelmi * glib/glib-sections.txt: Added g_rand_boolean and diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 034086c19..3eb8f1190 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -1094,6 +1094,7 @@ g_module_error GModuleCheckInit GModuleUnload +G_MODULE_SUFFIX G_MODULE_EXPORT G_MODULE_IMPORT diff --git a/docs/reference/glib/tmpl/modules.sgml b/docs/reference/glib/tmpl/modules.sgml index 9e33e67a1..0719be68d 100644 --- a/docs/reference/glib/tmpl/modules.sgml +++ b/docs/reference/glib/tmpl/modules.sgml @@ -91,8 +91,20 @@ prefix and suffix. This should be freed when no longer needed. -Opens a module. -If the module has already been opened, its reference count is incremented. +Opens a module. If the module has already been opened, its reference +count is incremented. + + + +First of all g_module_open() tries to open @file_name as a module. If +that fails and @file_name has the ".la"-suffix (and is a libtool +archive) it tries to open the corresponding module. If that fails and +it doesn't have the proper module suffix for that plaform +(#G_MODULE_SUFFIX,) this suffix will be appended and the coresponding +module will be opended. If that fails and @file_name doesn't have the +".la"-suffix, this suffix is appended and g_module_open() tries to +open the corresponding module. If eventually that fails as well, NULL +is returned. @file_name: the name of the file containing the module. @@ -183,6 +195,15 @@ It is passed the #GModule structure. @module: the module about to be unloaded. + + +Expands to the proper shared library suffix for the current platform +without the leading dot. For the most Unices and Linux this is "so", +for some HPUX versions this is "sl" and for Windows this is "dll". + + + + Used to declare functions exported by modules. diff --git a/gmodule/ChangeLog b/gmodule/ChangeLog index 3ffd54e71..364f25149 100644 --- a/gmodule/ChangeLog +++ b/gmodule/ChangeLog @@ -1,3 +1,23 @@ +2000-12-22 Sebastian Wilhelmi + + * gmodule.c: Make g_module_open more tolerant wrt to the module + name. First it tries to open the module as named, if that fails, + it checks, whether it is a libtool archive and parses it, if that + fails it appends the systems shared library suffix + (i.e. ".so") (if not already found) and tries again and if that + fails it tries to append the ".la" libtool suffix (if not already + found) and parses it. + + * gmodule.c: Lock recursive mutex during most module functions for + safety. + + * gmodule-dl.c: Return an error from _g_module_symbol only, if + dlerror says so. All other functions return an error as well, if + dlerror returns NULL. + + * testgmodule.c: Thanks to the above change the #ifdefs have + vanished. + 2000-10-15 Raja R Harinath * Makefile.am (BUILT_EXTRA_DIST): New variable. diff --git a/gmodule/gmodule-dl.c b/gmodule/gmodule-dl.c index 7b4b7c1c9..9df56d4ab 100644 --- a/gmodule/gmodule-dl.c +++ b/gmodule/gmodule-dl.c @@ -71,13 +71,17 @@ /* --- functions --- */ static gchar* -fetch_dlerror (void) +fetch_dlerror (gboolean replace_null) { gchar *msg = dlerror (); - /* make sure we always return an error message != NULL */ + /* make sure we always return an error message != NULL, if + * expected to do so. */ - return msg ? msg : "unknown dl-error"; + if (!msg && replace_null) + return "unknown dl-error"; + + return msg; } static gpointer @@ -88,7 +92,7 @@ _g_module_open (const gchar *file_name, handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); if (!handle) - g_module_set_error (fetch_dlerror ()); + g_module_set_error (fetch_dlerror (TRUE)); return handle; } @@ -104,7 +108,7 @@ _g_module_self (void) handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY); if (!handle) - g_module_set_error (fetch_dlerror ()); + g_module_set_error (fetch_dlerror (TRUE)); return handle; } @@ -121,7 +125,7 @@ _g_module_close (gpointer handle, if (is_unref) { if (dlclose (handle) != 0) - g_module_set_error (fetch_dlerror ()); + g_module_set_error (fetch_dlerror (TRUE)); } } @@ -133,7 +137,7 @@ _g_module_symbol (gpointer handle, p = dlsym (handle, symbol_name); if (!p) - g_module_set_error (fetch_dlerror ()); + g_module_set_error (fetch_dlerror (FALSE)); return p; } diff --git a/gmodule/gmodule.c b/gmodule/gmodule.c index b43704689..d3aefcf06 100644 --- a/gmodule/gmodule.c +++ b/gmodule/gmodule.c @@ -28,11 +28,19 @@ * MT safe */ +#ifdef HAVE_CONFIG_H +# include +#endif #include "gmodule.h" #include "gmoduleconf.h" #include #include - +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* We maintain a list of modules, so we can reference count them. * That's needed because some platforms don't support refernce counts on @@ -71,7 +79,6 @@ static inline GModule* g_module_find_by_name (const gchar *name); /* --- variables --- */ -G_LOCK_DEFINE_STATIC (GModule); const char *g_log_domain_gmodule = "GModule"; static GModule *modules = NULL; static GModule *main_module = NULL; @@ -85,7 +92,6 @@ g_module_find_by_handle (gpointer handle) GModule *module; GModule *retval = NULL; - G_LOCK (GModule); if (main_module && main_module->handle == handle) retval = main_module; else @@ -95,7 +101,6 @@ g_module_find_by_handle (gpointer handle) retval = module; break; } - G_UNLOCK (GModule); return retval; } @@ -106,14 +111,12 @@ g_module_find_by_name (const gchar *name) GModule *module; GModule *retval = NULL; - G_LOCK (GModule); for (module = modules; module; module = module->next) if (strcmp (name, module->file_name) == 0) { retval = module; break; } - G_UNLOCK (GModule); return retval; } @@ -177,6 +180,103 @@ g_module_supported (void) return TRUE; } +static gchar* +parse_libtool_archive (const gchar* libtool_name) +{ + const gint TOKEN_DLNAME = G_TOKEN_LAST + 1; + const gint TOKEN_INSTALLED = G_TOKEN_LAST + 2; + const gint TOKEN_LIBDIR = G_TOKEN_LAST + 3; + gchar *lt_dlname = NULL; + gboolean lt_installed = TRUE; + gchar *lt_libdir = NULL; + gchar *name; + GTokenType token; + GScanner *scanner; + + int fd = open (libtool_name, O_RDONLY, 0); + if (fd < 0) + { + g_module_set_error ("couldn't open libtool archive"); + return NULL; + } + /* search libtool's dlname specification */ + scanner = g_scanner_new (NULL); + g_scanner_input_file (scanner, fd); + scanner->config->symbol_2_token = TRUE; + g_scanner_scope_add_symbol (scanner, 0, "dlname", + GUINT_TO_POINTER (TOKEN_DLNAME)); + g_scanner_scope_add_symbol (scanner, 0, "installed", + GUINT_TO_POINTER (TOKEN_INSTALLED)); + g_scanner_scope_add_symbol (scanner, 0, "libdir", + GUINT_TO_POINTER (TOKEN_LIBDIR)); + while (!g_scanner_eof (scanner)) + { + token = g_scanner_get_next_token (scanner); + if (token == TOKEN_DLNAME || token == TOKEN_INSTALLED || + token == TOKEN_LIBDIR) + { + if (g_scanner_get_next_token (scanner) != '=' || + g_scanner_get_next_token (scanner) != + (token == TOKEN_INSTALLED ? + G_TOKEN_IDENTIFIER : G_TOKEN_STRING)) + { + g_module_set_error ("libtool archive has unknown format"); + + g_free (lt_dlname); + g_free (lt_libdir); + g_scanner_destroy (scanner); + close (fd); + + return NULL; + } + else + { + if (token == TOKEN_DLNAME) + { + g_free (lt_dlname); + lt_dlname = g_strdup (scanner->value.v_string); + } + else if (token == TOKEN_INSTALLED) + lt_installed = + strcmp (scanner->value.v_identifier, "yes") == 0; + else /* token == TOKEN_LIBDIR */ + { + g_free (lt_libdir); + lt_libdir = g_strdup (scanner->value.v_string); + } + } + } + } + + if (!lt_installed) + { + gchar *dir = g_path_get_dirname (libtool_name); + g_free (lt_libdir); + lt_libdir = g_strconcat (dir, G_DIR_SEPARATOR_S ".libs", NULL); + } + + name = g_module_build_path (lt_libdir, lt_dlname); + + g_free (lt_dlname); + g_free (lt_libdir); + g_scanner_destroy (scanner); + close (fd); + + return name; +} + +static inline gboolean +g_str_check_suffix (const gchar* string, const gchar* suffix) +{ + guint string_len = strlen (string); + guint suffix_len = strlen (suffix); + + return string_len >= suffix_len && + strcmp (string + string_len - suffix_len, suffix) == 0; +} + +static GStaticRecMutex g_module_global_lock = G_STATIC_REC_MUTEX_INIT; + GModule* g_module_open (const gchar *file_name, GModuleFlags flags) @@ -186,9 +286,9 @@ g_module_open (const gchar *file_name, SUPPORT_OR_RETURN (NULL); + g_static_rec_mutex_lock (&g_module_global_lock); if (!file_name) { - G_LOCK (GModule); if (!main_module) { handle = _g_module_self (); @@ -203,8 +303,8 @@ g_module_open (const gchar *file_name, main_module->next = NULL; } } - G_UNLOCK (GModule); + g_static_rec_mutex_unlock (&g_module_global_lock); return main_module; } @@ -214,11 +314,46 @@ g_module_open (const gchar *file_name, { module->ref_count++; + g_static_rec_mutex_unlock (&g_module_global_lock); return module; } - /* open the module */ + /* First we try to open the module as provided */ handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0); + + /* If not found, we check, if it is a libtool archive */ + if (!handle && g_str_check_suffix (file_name, ".la")) + { + gchar *name = parse_libtool_archive (file_name); + if (name) + { + handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0); + g_free (name); + } + } + + /* If still not found, we check, if it is a library name without suffix */ + if (!handle && !g_str_check_suffix (file_name, "." G_MODULE_SUFFIX)) + { + gchar *name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); + handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0); + g_free (name); + } + + /* If still not found, we check, if it is a libtool archive name + * without suffix */ + if (!handle && !g_str_check_suffix (file_name, ".la")) + { + gchar *la_name = g_strconcat (file_name, ".la", NULL); + gchar *name = parse_libtool_archive (la_name); + if (name) + { + handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0); + g_free (name); + } + g_free (la_name); + } + if (handle) { gchar *saved_error; @@ -233,6 +368,7 @@ g_module_open (const gchar *file_name, module->ref_count++; g_module_set_error (NULL); + g_static_rec_mutex_unlock (&g_module_global_lock); return module; } @@ -245,10 +381,8 @@ g_module_open (const gchar *file_name, module->ref_count = 1; module->is_resident = FALSE; module->unload = NULL; - G_LOCK (GModule); module->next = modules; modules = module; - G_UNLOCK (GModule); /* check initialization */ if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init)) @@ -273,7 +407,8 @@ g_module_open (const gchar *file_name, g_free (saved_error); } - + + g_static_rec_mutex_unlock (&g_module_global_lock); return module; } @@ -285,6 +420,8 @@ g_module_close (GModule *module) g_return_val_if_fail (module != NULL, FALSE); g_return_val_if_fail (module->ref_count > 0, FALSE); + g_static_rec_mutex_lock (&g_module_global_lock); + module->ref_count--; if (!module->ref_count && !module->is_resident && module->unload) @@ -303,7 +440,6 @@ g_module_close (GModule *module) last = NULL; - G_LOCK (GModule); node = modules; while (node) { @@ -319,7 +455,6 @@ g_module_close (GModule *module) node = last->next; } module->next = NULL; - G_UNLOCK (GModule); _g_module_close (module->handle, FALSE); g_free (module->file_name); @@ -327,6 +462,7 @@ g_module_close (GModule *module) g_free (module); } + g_static_rec_mutex_unlock (&g_module_global_lock); return g_module_error() == NULL; } @@ -359,6 +495,8 @@ g_module_symbol (GModule *module, g_return_val_if_fail (symbol_name != NULL, FALSE); g_return_val_if_fail (symbol != NULL, FALSE); + g_static_rec_mutex_lock (&g_module_global_lock); + #ifdef G_MODULE_NEED_USCORE { gchar *name; @@ -380,11 +518,10 @@ g_module_symbol (GModule *module, g_module_set_error (error); g_free (error); *symbol = NULL; - - return FALSE; } - return TRUE; + g_static_rec_mutex_unlock (&g_module_global_lock); + return !module_error; } gchar* diff --git a/gmodule/testgmodule.c b/gmodule/testgmodule.c index db2137567..17257e394 100644 --- a/gmodule/testgmodule.c +++ b/gmodule/testgmodule.c @@ -54,16 +54,9 @@ main (int arg, string = g_get_current_dir (); g_print ("testgmodule (%s):\n", string); -#if (G_MODULE_IMPL == G_MODULE_IMPL_WIN32) - plugin_a = g_strconcat (string, "\\libgplugin_a.dll", NULL); - plugin_b = g_strconcat (string, "\\libgplugin_b.dll", NULL); -#elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD) - plugin_a = g_strconcat (string, "/.libs/", "libgplugin_a.sl", NULL); - plugin_b = g_strconcat (string, "/.libs/", "libgplugin_b.sl", NULL); -#else /* neither DLD nor WIN32 */ - plugin_a = g_strconcat (string, "/.libs/", "libgplugin_a.so", NULL); - plugin_b = g_strconcat (string, "/.libs/", "libgplugin_b.so", NULL); -#endif + plugin_a = g_strconcat (string, G_DIR_SEPARATOR_S "libgplugin_a", NULL); + plugin_b = g_strconcat (string, G_DIR_SEPARATOR_S "libgplugin_b", NULL); + g_free (string); /* module handles diff --git a/tests/.cvsignore b/tests/.cvsignore index 4f67021e9..9256a231b 100644 --- a/tests/.cvsignore +++ b/tests/.cvsignore @@ -6,6 +6,8 @@ Makefile.in makefile.msc makefile.mingw _libs +libmoduletestplugin_a.la +libmoduletestplugin_b.la array-test date-test dirname-test @@ -13,6 +15,7 @@ hash-test list-test mainloop-test markup-test +module-test node-test queue-test rand-test diff --git a/tests/Makefile.am b/tests/Makefile.am index ce1a10810..f96efba59 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,6 +20,7 @@ test_programs = \ hash-test \ list-test \ mainloop-test \ + module-test \ node-test \ queue-test \ rand-test \ @@ -45,6 +46,7 @@ TESTS_ENVIRONMENT = srcdir=$(srcdir) progs_LDADD = $(EFENCE) $(top_builddir)/libglib-1.3.la $(EFENCE) thread_LDADD = $(progs_LDADD) $(top_builddir)/gthread/libgthread-1.3.la @G_THREAD_LIBS@ +module_LDADD = $(progs_LDADD) $(top_builddir)/gmodule/libgmodule-1.3.la @G_MODULE_LIBS@ array_test_LDADD = $(progs_LDADD) date_test_LDADD = $(progs_LDADD) @@ -54,6 +56,8 @@ hash_test_LDADD = $(progs_LDADD) list_test_LDADD = $(progs_LDADD) mainloop_test_LDADD = $(thread_LDADD) markup_test_LDADD = $(progs_LDADD) +module_test_LDADD = $(module_LDADD) +module_test_LDFLAGS = @G_MODULE_LDFLAGS@ node_test_LDADD = $(progs_LDADD) queue_test_LDADD = $(progs_LDADD) rand_test_LDADD = $(progs_LDADD) @@ -68,6 +72,20 @@ threadpool_test_LDADD = $(thread_LDADD) tree_test_LDADD = $(progs_LDADD) type_test_LDADD = $(progs_LDADD) +lib_LTLIBRARIES = libmoduletestplugin_a.la libmoduletestplugin_b.la + +# Prevent those libs from being installed +install-libLTLIBRARIES: + : + +libmoduletestplugin_a_la_SOURCES = libmoduletestplugin_a.c +libmoduletestplugin_a_la_LDFLAGS = @G_MODULE_LDFLAGS@ -avoid-version -module +libmoduletestplugin_a_la_LIBADD = @G_MODULE_LIBS@ + +libmoduletestplugin_b_la_SOURCES = libmoduletestplugin_b.c +libmoduletestplugin_b_la_LDFLAGS = @G_MODULE_LDFLAGS@ -avoid-version -module +libmoduletestplugin_b_la_LIBADD = @G_MODULE_LIBS@ + makefile.msc: $(top_builddir)/config.status $(top_srcdir)/tests/makefile.msc.in cd $(top_builddir) && CONFIG_FILES=tests/$@ CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/tests/libmoduletestplugin_a.c b/tests/libmoduletestplugin_a.c new file mode 100644 index 000000000..33d0635fa --- /dev/null +++ b/tests/libmoduletestplugin_a.c @@ -0,0 +1,68 @@ +/* libgplugin_a.c - test plugin for testgmodule + * Copyright (C) 1998 Tim Janik + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include +#include + +G_MODULE_EXPORT gchar* gplugin_a_state; + +G_MODULE_EXPORT void +gplugin_a_func (void) +{ + gplugin_a_state = "Hello world"; +} + +G_MODULE_EXPORT void +gplugin_clash_func (void) +{ + gplugin_a_state = "plugin clash"; +} + +G_MODULE_EXPORT void +g_clash_func (void) +{ + gplugin_a_state = "global clash"; +} + +G_MODULE_EXPORT void +gplugin_say_boo_func (void) +{ + gplugin_a_state = "BOOH"; +} + +G_MODULE_EXPORT void +gplugin_a_module_func (GModule *module) +{ + void (*f) (void) = NULL; + + if (!g_module_symbol (module, "gplugin_say_boo_func", (gpointer) &f)) + { + g_print ("error: %s\n", g_module_error ()); + exit (1); + } + + f (); +} diff --git a/tests/libmoduletestplugin_b.c b/tests/libmoduletestplugin_b.c new file mode 100644 index 000000000..a9df3dda8 --- /dev/null +++ b/tests/libmoduletestplugin_b.c @@ -0,0 +1,67 @@ +/* libgplugin_b.c - test plugin for testgmodule + * Copyright (C) 1998 Tim Janik + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include + +G_MODULE_EXPORT gchar* gplugin_b_state; + +G_MODULE_EXPORT const gchar* +g_module_check_init (GModule *module) +{ + gplugin_b_state = "check-init"; + + return NULL; +} + +G_MODULE_EXPORT void +g_module_unload (GModule *module) +{ + gplugin_b_state = "unloaded"; +} + +G_MODULE_EXPORT void +gplugin_b_func (void) +{ + gplugin_b_state = "Hello world"; +} + +G_MODULE_EXPORT void +gplugin_clash_func (void) +{ + gplugin_b_state = "plugin clash"; +} + +G_MODULE_EXPORT void +g_clash_func (void) +{ + gplugin_b_state = "global clash"; +} + +G_MODULE_EXPORT void +gplugin_say_boo_func (void) +{ + gplugin_b_state = "BOOH"; +} diff --git a/tests/module-test.c b/tests/module-test.c new file mode 100644 index 000000000..c83dfb2bb --- /dev/null +++ b/tests/module-test.c @@ -0,0 +1,198 @@ +/* module-test.c - test program for GMODULE + * Copyright (C) 1998 Tim Janik + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include + +gchar* global_state; + +G_MODULE_EXPORT void +g_clash_func (void) +{ + global_state = "global clash"; +} + +typedef void (*SimpleFunc) (void); +typedef void (*GModuleFunc) (GModule *); + +static gchar **gplugin_a_state; +static gchar **gplugin_b_state; + +static void +compare (const gchar *desc, const gchar *expected, const gchar *found) +{ + if (!expected && !found) + return; + + if (expected && found && strcmp (expected, found) == 0) + return; + + g_error ("error: %s state should have been \"%s\", but is \"%s\"", + desc, expected ? expected : "NULL", found ? found : "NULL"); +} + +static void +test_states (const gchar *global, const gchar *gplugin_a, + const gchar *gplugin_b) +{ + compare ("global", global, global_state); + compare ("Plugin A", gplugin_a, *gplugin_a_state); + compare ("Plugin B", gplugin_b, *gplugin_b_state); + + global_state = *gplugin_a_state = *gplugin_b_state = NULL; +} + +static SimpleFunc plugin_clash_func = NULL; + +int +main (int arg, + char *argv[]) +{ + GModule *module_self, *module_a, *module_b; + gchar *dir; + gchar *plugin_a, *plugin_b; + SimpleFunc f_a, f_b, f_self; + GModuleFunc gmod_f; + + if (!g_module_supported ()) + return 0; + + dir = g_get_current_dir (); + + plugin_a = g_strconcat (dir, G_DIR_SEPARATOR_S "libmoduletestplugin_a", + NULL); + plugin_b = g_strconcat (dir, G_DIR_SEPARATOR_S "libmoduletestplugin_b", + NULL); + + g_free (dir); + + /* module handles */ + + module_self = g_module_open (NULL, G_MODULE_BIND_LAZY); + if (!module_self) + g_error ("error: %s", g_module_error ()); + + if (!g_module_symbol (module_self, "g_module_close", (gpointer) &f_self)) + g_error ("error: %s", g_module_error ()); + + module_a = g_module_open (plugin_a, G_MODULE_BIND_LAZY); + if (!module_a) + g_error ("error: %s", g_module_error ()); + + module_b = g_module_open (plugin_b, G_MODULE_BIND_LAZY); + if (!module_b) + g_error ("error: %s", g_module_error ()); + + /* get plugin state vars */ + + if (!g_module_symbol (module_a, "gplugin_a_state", + (gpointer) &gplugin_a_state)) + g_error ("error: %s", g_module_error ()); + + if (!g_module_symbol (module_b, "gplugin_b_state", + (gpointer) &gplugin_b_state)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, "check-init"); + + /* get plugin specific symbols and call them + */ + if (!g_module_symbol (module_a, "gplugin_a_func", (gpointer) &f_a)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + if (!g_module_symbol (module_b, "gplugin_b_func", (gpointer) &f_b)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + f_a (); + test_states (NULL, "Hello world", NULL); + + f_b (); + test_states (NULL, NULL, "Hello world"); + + /* get and call globally clashing functions + */ + + if (!g_module_symbol (module_self, "g_clash_func", (gpointer) &f_self)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + if (!g_module_symbol (module_a, "g_clash_func", (gpointer) &f_a)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + if (!g_module_symbol (module_b, "g_clash_func", (gpointer) &f_b)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + f_self (); + test_states ("global clash", NULL, NULL); + + f_a (); + test_states (NULL, "global clash", NULL); + + f_b (); + test_states (NULL, NULL, "global clash"); + + /* get and call clashing plugin functions */ + + if (!g_module_symbol (module_a, "gplugin_clash_func", (gpointer) &f_a)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + if (!g_module_symbol (module_b, "gplugin_clash_func", (gpointer) &f_b)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + plugin_clash_func = f_a; + plugin_clash_func (); + test_states (NULL, "plugin clash", NULL); + + plugin_clash_func = f_b; + plugin_clash_func (); + test_states (NULL, NULL, "plugin clash"); + + /* call gmodule function from A */ + + if (!g_module_symbol (module_a, "gplugin_a_module_func", (gpointer) &gmod_f)) + g_error ("error: %s", g_module_error ()); + test_states (NULL, NULL, NULL); + + gmod_f (module_b); + test_states (NULL, NULL, "BOOH"); + + gmod_f (module_a); + test_states (NULL, "BOOH", NULL); + + /* unload plugins */ + + if (!g_module_close (module_a)) + g_error ("error: %s", g_module_error ()); + + if (!g_module_close (module_b)) + g_error ("error: %s", g_module_error ()); + + return 0; +}