From da8c3be66f356d5fb29d2a59a226512e145c6328 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Mon, 18 Aug 2008 08:18:16 +0000 Subject: [PATCH] Add a proposal for a module/plugins API that should match every requirement I received. It's a little huge right now, but work quite nicely. It support "static" module, version, recursive lookup and should be able to replace the module/plugins support in evas and ecore. SVN revision: 35534 --- legacy/eina/configure.in | 6 + legacy/eina/src/include/eina_file.h | 4 +- legacy/eina/src/include/eina_mempool.h | 3 + legacy/eina/src/include/eina_module.h | 52 +- legacy/eina/src/lib/Makefile.am | 3 + legacy/eina/src/lib/eina_file.c | 91 +- legacy/eina/src/lib/eina_mempool.c | 66 +- legacy/eina/src/lib/eina_module.c | 1035 +++++++++++++---- .../mp/chained_pool/eina_chained_mempool.c | 5 +- .../mp/ememoa_fixed/eina_ememoa_fixed.c | 5 +- .../mp/ememoa_unknown/eina_ememoa_unknown.c | 4 +- .../modules/mp/pass_through/pass_through.c | 4 +- legacy/eina/src/tests/Makefile.am | 11 +- legacy/eina/src/tests/eina_suite.c | 1 + legacy/eina/src/tests/eina_suite.h | 1 + legacy/eina/src/tests/eina_test_module.c | 114 ++ 16 files changed, 1060 insertions(+), 345 deletions(-) create mode 100644 legacy/eina/src/tests/eina_test_module.c diff --git a/legacy/eina/configure.in b/legacy/eina/configure.in index b317ff53cf..eda7e1d403 100644 --- a/legacy/eina/configure.in +++ b/legacy/eina/configure.in @@ -24,6 +24,12 @@ version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN" AC_SUBST(VMAJ) AC_SUBST(version_info) +### Needed information + +MODULE_ARCH="$host_os-$host_cpu" +AC_SUBST(MODULE_ARCH) +AC_DEFINE_UNQUOTED(MODULE_ARCH, "${MODULE_ARCH}", "Module architecture") + ### Additional options to configure # Unit tests diff --git a/legacy/eina/src/include/eina_file.h b/legacy/eina/src/include/eina_file.h index 8b9534d73e..8204773e4f 100644 --- a/legacy/eina/src/include/eina_file.h +++ b/legacy/eina/src/include/eina_file.h @@ -27,9 +27,9 @@ */ typedef void (*Eina_File_Dir_List_Cb)(const char *name, const char *path, void *data); +#define EINA_FILE_DIR_LIST_CB(Function) ((Eina_File_Dir_List_Cb)Function) -EAPI void eina_file_dir_list(const char *dir, int recursive, Eina_File_Dir_List_Cb cb, void *data); -EAPI void eina_file_path_nth_get(const char *path, int n, char **left, char **right); +EAPI Eina_Bool eina_file_dir_list(const char *dir, Eina_Bool recursive, Eina_File_Dir_List_Cb cb, void *data); /** @} */ diff --git a/legacy/eina/src/include/eina_mempool.h b/legacy/eina/src/include/eina_mempool.h index 69d29cd031..673c3eb262 100644 --- a/legacy/eina/src/include/eina_mempool.h +++ b/legacy/eina/src/include/eina_mempool.h @@ -20,6 +20,7 @@ #define EINA_MEMPOOL_H_ #include "eina_types.h" +#include "eina_error.h" /** * @defgroup Memory_Pool_Group Memory Pool @@ -27,6 +28,8 @@ */ typedef struct _Eina_Mempool Eina_Mempool; +EAPI extern Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE; + EAPI int eina_mempool_init(void); EAPI int eina_mempool_shutdown(void); diff --git a/legacy/eina/src/include/eina_module.h b/legacy/eina/src/include/eina_module.h index c7ef23db6d..7a8e658770 100644 --- a/legacy/eina/src/include/eina_module.h +++ b/legacy/eina/src/include/eina_module.h @@ -26,25 +26,51 @@ * @defgroup Module_Group Module * @{ */ - typedef struct _Eina_Module Eina_Module; +typedef struct _Eina_Module_Group Eina_Module_Group; +typedef struct _Eina_Module_Export Eina_Module_Export; -typedef int (*Eina_Module_Cb)(Eina_Module *m, void *data); +typedef Eina_Bool (*Eina_Module_Cb)(Eina_Module *m, void *data); +struct _Eina_Module_Export +{ + const char *name; + const char *version; + const char *type; + const void *object; +}; -EAPI Eina_Module * eina_module_new(const char *file); -EAPI void eina_module_free(Eina_Module *m); +EAPI int eina_module_init(void); +EAPI int eina_module_shutdown(void); +EAPI void eina_module_root_add(const char *root_path); -EAPI int eina_module_load(Eina_Module *m); -EAPI void eina_module_unload(Eina_Module *m); +EAPI Eina_Module_Group *eina_module_group_new(void); +EAPI void eina_module_group_delete(Eina_Module_Group *group); -EAPI char * eina_module_path_get(Eina_Module *m); -EAPI char * eina_module_name_get(Eina_Module *m); -EAPI void * eina_module_symbol_get(Eina_Module *m, const char *symbol); +EAPI void eina_module_path_register(Eina_Module_Group *modules, const char *path, Eina_Bool recursive); +EAPI void eina_module_app_register(Eina_Module_Group *modules, const char *app, const char *types, const char *version); +EAPI void eina_module_register(Eina_Module_Group *modules, const Eina_Module_Export *static_module); -EAPI Eina_List * eina_module_list_get(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data); -EAPI void eina_module_list_load(Eina_List *list); -EAPI void eina_module_list_unload(Eina_List *list); -EAPI void eina_module_list_free(Eina_List *list); +EAPI Eina_List *eina_module_list_new(Eina_Module_Group *modules, Eina_Module_Cb cb, void *data); +EAPI void eina_module_list_delete(Eina_List *modules); + +EAPI Eina_Module *eina_module_new(Eina_Module_Group *modules, const char *name); +EAPI void eina_module_delete(Eina_Module *modules); + +EAPI Eina_Bool eina_module_load(Eina_Module *module); +EAPI void eina_module_unload(Eina_Module *module); + +EAPI void eina_module_list_load(const Eina_List *list); +EAPI void eina_module_list_unload(const Eina_List *list); + +EAPI const char *eina_module_path_get(Eina_Module *module); +EAPI void *eina_module_symbol_get(Eina_Module *module, const char *symbol); + +EAPI void *eina_module_export_object_get(Eina_Module *module); +EAPI const char *eina_module_export_type_get(Eina_Module *module); +EAPI const char *eina_module_export_version_get(Eina_Module *module); +EAPI const char *eina_module_export_name_get(Eina_Module *module); + +#define EINA_MODULE(Name, Type, Version, Object) EAPI Eina_Module_Export Eina_Export = { Name, Version, Type, Object }; /** @} */ diff --git a/legacy/eina/src/lib/Makefile.am b/legacy/eina/src/lib/Makefile.am index 28c08590ba..84aeb7398f 100644 --- a/legacy/eina/src/lib/Makefile.am +++ b/legacy/eina/src/lib/Makefile.am @@ -2,6 +2,9 @@ MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = \ -I$(top_srcdir)/src/include \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ @COVERAGE_CFLAGS@ lib_LTLIBRARIES = libeina.la diff --git a/legacy/eina/src/lib/eina_file.c b/legacy/eina/src/lib/eina_file.c index 87e36dfcd3..91d9ff42d5 100644 --- a/legacy/eina/src/lib/eina_file.c +++ b/legacy/eina/src/lib/eina_file.c @@ -18,6 +18,9 @@ #define _GNU_SOURCE #include +#include +#include +#include #include "eina_file.h" #include "eina_private.h" @@ -33,76 +36,50 @@ * @param cb The callback to be called * @param data The data to pass to the callback */ -EAPI void eina_file_dir_list(const char *dir, int recursive, Eina_File_Dir_List_Cb cb, void *data) +EAPI Eina_Bool +eina_file_dir_list(const char *dir, Eina_Bool recursive, Eina_File_Dir_List_Cb cb, void *data) { struct dirent *de; DIR *d; - assert(cb); - + if (!cb) return EINA_FALSE; + d = opendir(dir); - if (!d) - return; + if (!d) return EINA_FALSE; while ((de = readdir(d))) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; - + cb(de->d_name, dir, data); /* d_type is only available on linux and bsd (_BSD_SOURCE) */ - if ((recursive) && (de->d_type == DT_DIR)) - { - char path[PATH_MAX]; - - snprintf(path, PATH_MAX, "%s/%s", dir, de->d_name); + + if (recursive == EINA_TRUE) { + char *path; + + path = alloca(strlen(dir) + strlen(de->d_name) + 2); + strcpy(path, dir); + strcat(path, "/"); + strcat(path, de->d_name); + + if (de->d_type == DT_UNKNOWN) { + struct stat st; + + if (stat(path, &st)) + continue ; + + if (!S_ISDIR(st.st_mode)) + continue ; + } else if (de->d_type != DT_DIR) { + continue ; + } + eina_file_dir_list(path, recursive, cb, data); } } - closedir(d); -} -/** - * - */ -EAPI void eina_file_path_nth_get(const char *path, int n, char **left, char **right) -{ - char *p; - char *end; - char *tmp; - char *delim; - int inc; - int num = 0; - - if (!left && !right) - return; - - if (n > 0) - { - p = (char *)path; - inc = 1; - end = (char *)path + strlen(path); - } - else - { - p = (char *)path + strlen(path); - inc = -1; - end = (char *)path; - } - for (tmp = p, delim = p; tmp != end && num != n; tmp += inc) - { - if (*tmp == '/') - { - num += inc; - delim = tmp; - } - } - if (left) - { - *left = strndup(path, delim - path + 1); - } - if (right) - { - *right = strdup(delim + 1); - } -} + closedir(d); + + return EINA_TRUE; +} diff --git a/legacy/eina/src/lib/eina_mempool.c b/legacy/eina/src/lib/eina_mempool.c index c9d7902303..76e6b7964d 100644 --- a/legacy/eina/src/lib/eina_mempool.c +++ b/legacy/eina/src/lib/eina_mempool.c @@ -23,9 +23,11 @@ /*============================================================================* * Local * *============================================================================*/ -static Eina_List *_modules; +static Eina_Module_Group *_group; static int _init_count = 0; +EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0; + struct _Eina_Mempool { #ifdef DEBUG @@ -35,33 +37,37 @@ struct _Eina_Mempool Eina_Mempool_Backend *backend; void *backend_data; }; + static Eina_Mempool * _new_from_buffer(const char *module, const char *context, const char *options, va_list args) { - Eina_List *l; + Eina_Mempool *mp; + Eina_Module *m; - /* load the module with filename == name */ - for (l = _modules; l; l = eina_list_next(l)) - { - Eina_Module *m; - - m = eina_list_data(l); - /* check if the requested module name exists */ - if (!strncmp(eina_module_name_get(m), module, strlen(module) + 1)) - { - Eina_Mempool *mp; - - mp = malloc(sizeof(Eina_Mempool)); - eina_module_load(m); - mp->module = m; - mp->backend = eina_module_symbol_get(m, "mp_backend"); - mp->backend_data = mp->backend->init(context, options, args); - - return mp; - } + eina_error_set(0); + m = eina_module_new(_group, module); + if (!m) return NULL; + if (eina_module_load(m) == EINA_FALSE) { + eina_error_set(EINA_ERROR_NOT_MEMPOOL_MODULE); + goto on_error; } + + mp = malloc(sizeof(Eina_Mempool)); + if (!mp) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + goto on_error; + } + mp->module = m; + mp->backend = eina_module_export_object_get(m); + mp->backend_data = mp->backend->init(context, options, args); + + return mp; + + on_error: + if (m) eina_module_delete(m); return NULL; } + /*============================================================================* * API * *============================================================================*/ @@ -73,11 +79,19 @@ eina_mempool_init(void) { if (!_init_count) { - _modules = eina_module_list_get("/usr/local/lib/eina/modules/mp", 0, NULL, NULL); + eina_module_init(); + + _group = eina_module_group_new(); + if (!_group) return 0; + + eina_module_app_register(_group, "eina", "mp", NULL); + + EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_register("Not a memory pool module."); } /* get all the modules */ return ++_init_count; } + /** * */ @@ -90,10 +104,12 @@ eina_mempool_shutdown(void) if (!_init_count) { /* remove the list of modules */ - eina_module_list_free(_modules); + eina_module_group_delete(_group); + eina_module_shutdown(); } return _init_count; } + /** * */ @@ -111,6 +127,7 @@ eina_mempool_new(const char *name, const char *context, const char *options, ... return mp; } + /** * */ @@ -122,6 +139,7 @@ EAPI void eina_mempool_delete(Eina_Mempool *mp) eina_module_unload(mp->module); free(mp); } + /** * */ @@ -132,6 +150,7 @@ EAPI void * eina_mempool_realloc(Eina_Mempool *mp, void *element, unsigned int s return mp->backend->realloc(mp->backend_data, element, size); } + /** * */ @@ -142,6 +161,7 @@ EAPI void * eina_mempool_alloc(Eina_Mempool *mp, unsigned int size) return mp->backend->alloc(mp->backend_data, size); } + /** * */ diff --git a/legacy/eina/src/lib/eina_module.c b/legacy/eina/src/lib/eina_module.c index bba83bd670..fcd795f566 100644 --- a/legacy/eina/src/lib/eina_module.c +++ b/legacy/eina/src/lib/eina_module.c @@ -16,286 +16,835 @@ * if not, see . */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "eina_module.h" #include "eina_file.h" #include "eina_private.h" +#include "eina_inlist.h" +#include #include #include #include /*============================================================================* - * Local * + * Local * *============================================================================*/ +#define MODULE_EXTENSION ".so" +#define MODULE_SUBDIR "/modules/" +#define MODULE_BASE_EXTENTION "module" + +typedef struct _Eina_Root_Directory Eina_Root_Directory; +typedef struct _Eina_Directory Eina_Directory; +typedef struct _Eina_Dir_List Eina_Dir_List; +typedef struct _Eina_Static Eina_Static; +typedef struct _Eina_App Eina_App; + struct _Eina_Module { -#ifdef DEBUG - unsigned int magic; -#endif - void *handle; - char *file; + Eina_Inlist __list; + + const char * path; + const char * name; + const Eina_App * app; + Eina_Module_Group * group; + + void * handle; + Eina_Module_Export * export; + + int references; + int load_references; + + Eina_Bool is_static_library; }; -#define MODULE_EXTENSION ".so" - - -typedef struct _Dir_List_Get_Cb_Data +struct _Eina_Directory { - Eina_Module_Cb cb; - void *data; - Eina_List *list; -} Dir_List_Get_Cb_Data; + Eina_Inlist __list; -typedef struct _Dir_List_Cb_Data + const char * path; + const char * extention; + + Eina_App * app; +}; + +struct _Eina_App { - Eina_Module_Cb cb; - void *data; -} Dir_List_Cb_Data; + const char * name; + const char * type; + const char * version; +}; -static int _dir_list_get_cb(Eina_Module *m, void *data) +struct _Eina_Static { - Dir_List_Get_Cb_Data *cb_data = data; - int ret = 1; - - if (cb_data->cb) - { - ret = cb_data->cb(m, cb_data->data); - } - if (ret) - { - cb_data->list = eina_list_append(cb_data->list, m); - } + Eina_Inlist __list; + Eina_Module_Export static_desc; +}; - return ret; +struct _Eina_Module_Group +{ + Eina_Inlist * lookup_directory; + Eina_Inlist * root_directory; + Eina_Inlist * recursive_directory; + Eina_Inlist * static_libraries; + + Eina_Inlist * loaded_module; +}; + +struct _Eina_Root_Directory +{ + Eina_Inlist __list; + + const char * path; +}; + +struct _Eina_Dir_List +{ + Eina_Module_Group *modules; + Eina_List *list; + void *data; + + Eina_Module_Cb cb; +}; + +static Eina_Inlist * root_directory; +static char *self_name = NULL; +static int _eina_module_count = 0; + +static Eina_Module * +_eina_module_build(Eina_Module_Group *modules, Eina_App *app, + const char *path, int length_path, + const char *name) +{ + Eina_Module *module; + void *handle; + + handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); + fprintf(stderr, "b [%s] %p\n", path, handle); + if (!handle) return NULL; + + module = calloc(1, sizeof (Eina_Module) + length_path + strlen(name) + 1); + if (!module) return NULL; + + module->path = (char*)(module + 1); + module->name = module->path + length_path; + module->group = modules; + module->app = app; + module->handle = handle; + module->references = 1; + module->is_static_library = EINA_FALSE; + + memcpy((char*) module->path, path, length_path); + strcpy((char*) module->name, name); + + if (eina_module_load(module) == EINA_TRUE) + return module; + + free(module); + return NULL; } -static void _dir_list_cb(const char *name, const char *path, void *data) +static Eina_Module * +_eina_module_try(Eina_Module_Group *modules, + const char *path, int length_path, + const char *filename, int length_filename) { - Dir_List_Cb_Data *cb_data = data; - unsigned int length; + Eina_Module *module; - length = strlen(name); - if (length < strlen(MODULE_EXTENSION) + 1) /* x.so */ - return; - if (!strcmp(name + length - strlen(MODULE_EXTENSION), - MODULE_EXTENSION)) - { - char file[PATH_MAX]; - Eina_Module *m; + module = calloc(1, sizeof (Eina_Module) + length_path + length_filename + 2); + if (!module) return NULL; - snprintf(file, PATH_MAX, "%s/%s", path, name); - m = eina_module_new(file); - if (!m) - return; - /* call the user provided cb on this module */ - cb_data->cb(m, cb_data->data); - } + module->path = (char*)(module + 1); + module->name = NULL; + module->group = modules; + module->app = NULL; + module->references = 1; + module->is_static_library = EINA_FALSE; + + strcpy((char*) module->path, path); + strcat((char*) module->path, "/"); + strcat((char*) module->path, filename); + + module->handle = dlopen(module->path, RTLD_LAZY | RTLD_GLOBAL); + if (!module->handle) goto on_error; + + if (eina_module_load(module) == EINA_TRUE) + { + module->name = module->export->name; + return module; + } + + on_error: + free(module); + return NULL; } + +static void +_eina_dir_module_cb(const char *name, const char *path, Eina_Dir_List *data) +{ + Eina_Module *module; + int length_name = strlen(name); + int length_path = strlen(path); + + if (strcmp(name + length_name - strlen(MODULE_EXTENSION), MODULE_EXTENSION)) + return ; + + module = _eina_module_try(data->modules, + path, length_path, + name, length_name); + if (!module) return ; + + if (data->cb(module, data->data) == EINA_TRUE) + { + data->modules->loaded_module = eina_inlist_prepend(data->modules->loaded_module, module); + data->list = eina_list_append(data->list, module); + + return ; + } + + eina_module_unload(module); + free(module); +} + /*============================================================================* - * API * + * Global * *============================================================================*/ -/** - * Calls the cb function for every module found on the directory path - * - * @param path The directory's path to search for modules - * @param recursive Iterate recursively on the path - * @param cb Callback function to call - * @param data Data passed to the callback function - */ -EAPI void eina_module_list(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data) +/*============================================================================* + * API * + *============================================================================*/ +EAPI int +eina_module_init(void) { - Dir_List_Cb_Data cb_data; - - assert(path); - - cb_data.cb = cb; - cb_data.data = data; - eina_file_dir_list(path, recursive, &_dir_list_cb, &cb_data); -} -/** - * Gets a list of modules found on the directory path - * - * @param path The directory's path to search for modules - * @param recursive Iterate recursively on the path - * @param cb Callback function to call, if the return value of the callback is zero - * it won't be added to the list, if it is one, it will. - * @param data Data passed to the callback function - */ -EAPI Eina_List * eina_module_list_get(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data) -{ - Dir_List_Get_Cb_Data list_get_cb_data; - Dir_List_Cb_Data list_cb_data; - - assert(path); - - list_get_cb_data.list = NULL; - list_get_cb_data.cb = cb; - list_get_cb_data.data = data; - - list_cb_data.cb = &_dir_list_get_cb; - list_cb_data.data = &list_get_cb_data; - - eina_file_dir_list(path, recursive, &_dir_list_cb, &list_cb_data); - - return list_get_cb_data.list; -} -/** - * Load every module on the list of modules - * @param list The list of modules - */ -EAPI void eina_module_list_load(Eina_List *list) -{ - Eina_List *l; - - for (l = list; l; l = eina_list_next(l)) - { - Eina_Module *m; - - m = eina_list_data(l); - eina_module_load(m); - } -} -/** - * To be documented - * FIXME: To be fixed - */ -EAPI void eina_module_list_unload(Eina_List *list) -{ - Eina_List *l; - - for (l = list; l; l = eina_list_next(l)) - { - Eina_Module *m; - - m = eina_list_data(l); - eina_module_unload(m); - } -} -/** - * Helper function that iterates over the list of modules and calls - * eina_module_delete on each - * - */ -EAPI void eina_module_list_free(Eina_List *list) -{ - Eina_List *l; - - for (l = list; l; l = eina_list_next(l)) - { - Eina_Module *m; - - m = eina_list_data(l); - eina_module_free(m); - } -} -/** - * To be documented - * FIXME: To be fixed - */ -EAPI int eina_module_load(Eina_Module *m) -{ - void *dl_handle; - - assert(m); - - if (m->handle) return 1; + char *prefix; + char *path; - dl_handle = dlopen(m->file, RTLD_LAZY); - if (!dl_handle) return 0; - - m->handle = dl_handle; - return 1; -} -/** - * To be documented - * FIXME: To be fixed - */ -EAPI Eina_Module * eina_module_new(const char *file) -{ - Eina_Module *m; - - assert(file); - /* TODO check that the file exists */ - - m = malloc(sizeof(Eina_Module)); -#ifdef DEBUG - /* TODO add the magic */ -#endif - m->file = strdup(file); - m->handle = NULL; - - return m; -} -/** - * To be documented - * FIXME: To be fixed - */ -EAPI void eina_module_free(Eina_Module *m) -{ - assert(m); + _eina_module_count++; -#ifdef DEBUG - /* TODO check the magic */ + if (_eina_module_count != 1) + goto end_init; + + /* Add some default path. */ + + /* 1. ~/lib/ */ + prefix = getenv("HOME"); + if (prefix) + { + #define SUBDIR_LIB "/lib" + + path = malloc(strlen(prefix) + strlen(SUBDIR_LIB) + 1); + if (path) + { + strcpy(path, prefix); + strcat(path, SUBDIR_LIB); + + eina_module_root_add(path); + + free(path); + } + } + + /* 2. $(EINA_MODULE_DIR)/ */ + prefix = getenv("EINA_MODULES_DIR"); + if (prefix) eina_module_root_add(prefix); + +#ifdef HAVE_DLADDR + { + Dl_info eina_dl; + /* 3. libeina.so/../ */ + if (dladdr(eina_module_init, &eina_dl)) + { + int length; + + self_name = strdup(eina_dl.dli_fname); + + prefix = strrchr(eina_dl.dli_fname, '/'); + + if (prefix) + { + length = strlen(prefix); + path = malloc(strlen(eina_dl.dli_fname) - length + 1); + if (path) + { + strncpy(path, eina_dl.dli_fname, strlen(eina_dl.dli_fname) - length); + path[strlen(eina_dl.dli_fname) - length] = 0; + + eina_module_root_add(path); + + free(path); + } + } + } + } +#else + self_name = malloc(strlen(PACKAGE_LIB_DIR) + strlen("/libeina.so") + 1); + if (self_name) + { + strcpy(self_name, PACKAGE_LIB_DIR); + strcat(self_name, "/libeina.so"); + } #endif - if (m->handle) - eina_module_unload(m); - free(m->file); - free(m); + + /* 4. PREFIX/ */ + prefix = PACKAGE_LIB_DIR; + if (prefix) eina_module_root_add(prefix); + + end_init: + return _eina_module_count; } -/** - * To be documented - * FIXME: To be fixed - */ -EAPI void eina_module_unload(Eina_Module *m) + +EAPI int +eina_module_shutdown(void) { - assert(m); -#ifdef DEBUG - /* TODO check the magic */ -#endif - if (!m->handle) - return; - dlclose(m->handle); + _eina_module_count--; + + if (_eina_module_count != 0) + goto end_shutdown; + + free(self_name); + self_name = NULL; + + while (root_directory) + { + Eina_Root_Directory *root; + + root = (Eina_Root_Directory*) root_directory; + + root_directory = eina_inlist_remove(root_directory, root_directory); + + free(root); + } + + end_shutdown: + return _eina_module_count; } -/** - * To be documented - * FIXME: To be fixed - */ -EAPI void * eina_module_symbol_get(Eina_Module *m, const char *symbol) + +EAPI void +eina_module_root_add(const char *root_path) { - assert(m); -#ifdef DEBUG - /* TODO check the magic */ -#endif - return dlsym(m->handle, symbol); + Eina_Root_Directory *root; + unsigned int length; + + if (!root_path) return ; + + /* Lookup if the path is already registered. */ + EINA_INLIST_ITER_NEXT(root_directory, root) + if (!strcmp(root->path, root_path)) + return ; + + /* Add it. */ + length = strlen(root_path) + 1; + + root = calloc(1, sizeof (Eina_Root_Directory) + length); + if (!root) return ; + + root->path = (char*)(root + 1); + memcpy((char*) root->path, root_path, length); + + root_directory = eina_inlist_prepend(root_directory, root); } -/** - * To be documented - * FIXME: To be fixed - */ -EAPI char * eina_module_path_get(Eina_Module *m) + +EAPI Eina_Module_Group * +eina_module_group_new(void) { - char *path; - - assert(m); -#ifdef DEBUG - /* TODO check the magic */ -#endif - eina_file_path_nth_get(m->file, -1, &path, NULL); - - return path; + Eina_Module_Group *new; + + new = calloc(1, sizeof (Eina_Module_Group)); + + return new; } -/** - * To be documented - * FIXME: To be fixed - */ -EAPI char * eina_module_name_get(Eina_Module *m) + +EAPI void +eina_module_group_delete(Eina_Module_Group *group) { - char *name; - - assert(m); -#ifdef DEBUG - /* TODO check the magic */ -#endif - eina_file_path_nth_get(m->file, -1, NULL, &name); - - return name; + if (!group) return ; + + while (group->lookup_directory) + { + Eina_Directory *dir = (Eina_Directory*) group->lookup_directory; + + group->lookup_directory = eina_inlist_remove(group->lookup_directory, group->lookup_directory); + + free(dir); + } + + while (group->static_libraries) + { + Eina_Static *slib = (Eina_Static*) group->static_libraries; + + group->static_libraries = eina_inlist_remove(group->static_libraries, group->static_libraries); + + free(slib); + } + + while (group->loaded_module) + eina_module_delete((Eina_Module*) group->loaded_module); + + free(group); +} + +EAPI void +eina_module_path_register(Eina_Module_Group *modules, const char *path, Eina_Bool recursive) +{ + Eina_Root_Directory *dir; + int length; + + if (!modules || !path) return ; + + length = strlen(path) + 1; + + dir = calloc(1, sizeof (Eina_Root_Directory) + length); + if (!dir) return ; + + dir->path = (const char*) (dir + 1); + memcpy((char*) dir->path, path, length); + + if (recursive) + modules->recursive_directory = eina_inlist_prepend(modules->recursive_directory, dir); + else + modules->root_directory = eina_inlist_prepend(modules->root_directory, dir); +} + +EAPI void +eina_module_app_register(Eina_Module_Group *modules, const char *app, const char *type, const char *version) +{ + Eina_Directory *dir; + int app_length; + int type_length; + int version_length; + int subdir_length; + int extention_length; + + if (!modules || !app) return ; + + app_length = strlen(app); + subdir_length = strlen(MODULE_SUBDIR); + extention_length = strlen(MODULE_ARCH) + strlen(MODULE_BASE_EXTENTION) + strlen(MODULE_EXTENSION) + 3; + + type_length = type ? strlen(type) + 1 : 0; + version_length = version ? strlen(version) + 1 : 0; + + dir = calloc(1, sizeof (Eina_Directory) + + app_length + subdir_length + type_length + 1 /* path length */ + + extention_length + version_length + 1 /* extention length */); + if (!dir) return ; + + /* Build app description. */ + dir->app = malloc(sizeof (Eina_App) + app_length + type_length + version_length + 1); + if (!dir->app) + { + free(dir); + return ; + } + dir->app->name = (char*) (dir->app + 1); + dir->app->type = dir->app->name + app_length + 1; + dir->app->version = dir->app->type + type_length; + memcpy((char*) dir->app->name, app, app_length + 1); + memcpy((char*) dir->app->type, type, type_length); + memcpy((char*) dir->app->version, version, version_length); + + /* Setup pointer. */ + dir->path = (const char*) (dir + 1); + dir->extention = dir->path + app_length + subdir_length + type_length + 1; + + /* Build path. "[app]/modules/{[type]/}" */ + strcpy((char*) dir->path, app); + strcat((char*) dir->path, MODULE_SUBDIR); + if (type) + { + strcat((char*) dir->path, type); + strcat((char*) dir->path, "/"); + } + + /* Build extention "/[MODULE_ARCH]/module{-[version]}.so" */ + strcpy((char*) dir->extention, "/"); + strcat((char*) dir->extention, MODULE_ARCH); + strcat((char*) dir->extention, "/"); + strcat((char*) dir->extention, MODULE_BASE_EXTENTION); + if (version) + { + strcat((char*) dir->extention, "-"); + strcat((char*) dir->extention, version); + } + strcat((char*) dir->extention, MODULE_EXTENSION); + + modules->lookup_directory = eina_inlist_prepend(modules->lookup_directory, dir); +} + +EAPI void +eina_module_register(Eina_Module_Group *modules, const Eina_Module_Export *static_module) +{ + Eina_Static *library; + + if (!modules || !static_module) return ; + + library = malloc(sizeof (Eina_Static)); + if (!library) return ; + + library->static_desc = *static_module; + + modules->static_libraries = eina_inlist_prepend(modules->static_libraries, library); +} + +EAPI Eina_Module * +eina_module_new(Eina_Module_Group *modules, const char *name) +{ + Eina_Root_Directory *root; + Eina_Directory *dir; + Eina_Module *module; + Eina_Static *slib; + char path[PATH_MAX]; + int length; + + if (!modules) return NULL; + + /* Lookup in loaded module. */ + EINA_INLIST_ITER_NEXT(modules->loaded_module, module) + if (!strcmp(module->name, name)) + { + module->references++; + + return module; + } + + /* Lookup in statically provided module. */ + EINA_INLIST_ITER_NEXT(modules->static_libraries, slib) + if (!strcmp(slib->static_desc.name, name)) + { + module = calloc(1, sizeof (Eina_Module)); + if (!module) return NULL; + + /* FIXME: Must retrieve the library path that provide slib->static_desc */ + module->path = self_name; + module->name = slib->static_desc.name; + module->export = &slib->static_desc; + module->group = modules; + module->references = 1; + module->is_static_library = EINA_TRUE; + + modules->loaded_module = eina_inlist_prepend(modules->loaded_module, module); + + return module; + } + + /* Lookup for apps in each root_directory. */ + EINA_INLIST_ITER_NEXT(root_directory, root) + EINA_INLIST_ITER_NEXT(modules->lookup_directory, dir) + { + length = snprintf(path, PATH_MAX, "%s/%s/%s/%s", + root->path, dir->path, name, dir->extention) + 1; + if (length > PATH_MAX) return NULL; + + module = _eina_module_build(modules, dir->app, + path, length, + name); + if (!module) continue ; + + modules->loaded_module = eina_inlist_prepend(modules->loaded_module, module); + return module; + } + + /* Lookup for apps with full path from root_dir. */ + EINA_INLIST_ITER_NEXT(modules->root_directory, root) + { + length = snprintf(path, PATH_MAX, "%s"MODULE_SUBDIR"%s/%s", + root->path, name, MODULE_BASE_EXTENTION""MODULE_EXTENSION) + 1; + if (length > PATH_MAX) return NULL; + + module = _eina_module_build(modules, NULL, + path, length, + name); + if (!module) continue ; + if (strcmp(module->export->name, name) != 0) + { + eina_module_unload(module); + free(module); + continue ; + } + + modules->loaded_module = eina_inlist_prepend(modules->loaded_module, module); + return module; + } + + return NULL; +} + +EAPI void +eina_module_delete(Eina_Module *module) +{ + if (!module) return ; + + module->references--; + + if (module->references != 0) return ; + + module->group->loaded_module = eina_inlist_remove(module->group->loaded_module, module); + + if (module->handle) dlclose(module->handle); + free(module); +} + +EAPI Eina_List * +eina_module_list_new(Eina_Module_Group *modules, Eina_Module_Cb cb, void *data) +{ + Eina_List *list = NULL; + Eina_Root_Directory *root; + Eina_Directory *dir; + Eina_Module *module; + Eina_Static *slib; + struct dirent *rent; + DIR *look; + Eina_Dir_List edl; + char path[PATH_MAX]; + char filename[PATH_MAX]; + int path_length; + + /* Test against already loaded module. */ + EINA_INLIST_ITER_NEXT(modules->loaded_module, module) + if (cb(module, data) == EINA_TRUE) + { + module->references++; + + list = eina_list_append(list, module); + } + + /* Test against static module. */ + EINA_INLIST_ITER_NEXT(modules->static_libraries, slib) + { + module = calloc(1, sizeof (Eina_Module)); + if (!module) return NULL; + + module->path = self_name; + module->name = slib->static_desc.name; + module->export = &slib->static_desc; + module->group = modules; + module->references = 1; + module->is_static_library = EINA_TRUE; + + if (cb(module, data) == EINA_TRUE) + { + modules->loaded_module = eina_inlist_prepend(modules->loaded_module, module); + list = eina_list_append(list, module); + } + else + free(module); + } + + /* Lookup for apps in each root_directory. */ + EINA_INLIST_ITER_NEXT(root_directory, root) + EINA_INLIST_ITER_NEXT(modules->lookup_directory, dir) + { + strcpy(path, root->path); + strcat(path, "/"); + strcat(path, dir->path); + + look = opendir(path); + if (!look) continue ; + + path_length = strlen(path); + + while ((rent = readdir(look))) + { + int length; + + length = snprintf(filename, PATH_MAX, "%s/%s/%s", + path, rent->d_name, dir->extention) + 1; + if (length > PATH_MAX) continue ; + + module = _eina_module_build(modules, dir->app, + filename, length, + rent->d_name); + if (!module) continue ; + + if (cb(module, data) == EINA_TRUE) + { + modules->loaded_module = eina_inlist_prepend(modules->loaded_module, module); + list = eina_list_append(list, module); + } + else + { + eina_module_unload(module); + free(module); + } + } + + closedir(look); + } + + edl.list = list; + edl.modules = modules; + edl.data = data; + edl.cb = cb; + + /* Lookup for apps with full path from root_dir. */ + EINA_INLIST_ITER_NEXT(modules->root_directory, root) + eina_file_dir_list(root->path, EINA_FALSE, EINA_FILE_DIR_LIST_CB(_eina_dir_module_cb), &edl); + + /* Lookup for library in a directory or recursively. */ + EINA_INLIST_ITER_NEXT(modules->recursive_directory, root) + eina_file_dir_list(root->path, EINA_TRUE, EINA_FILE_DIR_LIST_CB(_eina_dir_module_cb), &edl); + + return edl.list; +} + +EAPI void +eina_module_list_delete(Eina_List *modules) +{ + Eina_Module *module; + + while (modules) + { + module = eina_list_data(modules); + eina_module_delete(module); + + modules = eina_list_remove_list(modules, modules); + } +} + +EAPI Eina_Bool +eina_module_load(Eina_Module *module) +{ + if (!module) return EINA_FALSE; + + module->load_references++; + + if (module->load_references != 1) return EINA_FALSE; + + if (module->is_static_library == EINA_FALSE) + { + if (!module->handle) + module->handle = dlopen(module->path, RTLD_LAZY | RTLD_GLOBAL); + if (!module->handle) + return EINA_FALSE; + + module->export = dlsym(module->handle, "Eina_Export"); + } + + if (!module->export) goto on_error; + + if (!module->export->name) + goto on_error; + + if (module->app) + { + if (strcmp(module->app->name, module->export->name)) + goto on_error; + + if (module->app->type && module->export->type) + if (strcmp(module->app->type, module->export->type)) + goto on_error; + + if (module->export->version && module->app->version) + if (strcmp(module->app->version, module->export->version)) + goto on_error; + } + + return EINA_TRUE; + + on_error: + if (module->handle) + dlclose(module->handle); + module->handle = NULL; + + if (module->is_static_library == EINA_FALSE) + module->export = NULL; + + module->load_references--; + + return EINA_FALSE; +} + +EAPI void +eina_module_unload(Eina_Module *module) +{ + if (!module) return ; + + module->load_references--; + + if (module->load_references != 0) return ; + + if (module->handle) + dlclose(module->handle); + module->handle = NULL; + + if (module->is_static_library == EINA_FALSE) + module->export = NULL; +} + +EAPI void +eina_module_list_load(const Eina_List *list) +{ + while (list) + { + eina_module_load(eina_list_data(list)); + + list = eina_list_next(list); + } +} + +EAPI void +eina_module_list_unload(const Eina_List *list) +{ + while (list) + { + eina_module_unload(eina_list_data(list)); + + list = eina_list_next(list); + } +} + +EAPI const char * +eina_module_path_get(Eina_Module *module) +{ + if (!module) return NULL; + return module->path; +} + +EAPI void * +eina_module_symbol_get(Eina_Module *module, const char *symbol) +{ + if (!module) return NULL; + if (module->load_references <= 0) return NULL; + /* dlopen of NULL give a handler to the main program. */ + if (!module->handle) module->handle = dlopen(NULL, RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL); + if (!module->handle) return NULL; + + return dlsym(module->handle, symbol); +} + +EAPI void * +eina_module_export_object_get(Eina_Module *module) +{ + if (!module) return NULL; + if (module->load_references <= 0) return NULL; + + return (void*) module->export->object; +} + +EAPI const char * +eina_module_export_type_get(Eina_Module *module) +{ + if (!module) return NULL; + if (module->load_references <= 0) return NULL; + + return module->export->type; +} + +EAPI const char * +eina_module_export_version_get(Eina_Module *module) +{ + if (!module) return NULL; + if (module->load_references <= 0) return NULL; + + return module->export->version; +} + +EAPI const char * +eina_module_export_name_get(Eina_Module *module) +{ + if (!module) return NULL; + if (module->load_references <= 0) return NULL; + + return module->export->name; } diff --git a/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c b/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c index 0a5fd107e4..e40f5c7ba0 100644 --- a/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c +++ b/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c @@ -28,6 +28,7 @@ #include "eina_inlist.h" #include "eina_error.h" +#include "eina_module.h" #include "eina_private.h" @@ -209,10 +210,12 @@ eina_chained_mempool_shutdown(void *data) free(mp); } -Eina_Mempool_Backend mp_backend = { +static Eina_Mempool_Backend mp_backend = { .init = &eina_chained_mempool_init, .shutdown = &eina_chained_mempool_shutdown, .realloc = &eina_chained_mempool_realloc, .alloc = &eina_chained_mempool_malloc, .free = &eina_chained_mempool_free }; + +EINA_MODULE("chaine_mempool", "mp", NULL, &mp_backend); diff --git a/legacy/eina/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c b/legacy/eina/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c index c3beee1a8c..9b38109c8b 100644 --- a/legacy/eina/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c +++ b/legacy/eina/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c @@ -29,6 +29,7 @@ #include "eina_inlist.h" #include "eina_error.h" +#include "eina_module.h" #include "eina_private.h" @@ -130,7 +131,7 @@ eina_ememoa_fixed_shutdown(void *data) free(efm); } -Eina_Mempool_Backend mp_backend = { +static Eina_Mempool_Backend mp_backend = { .init = &eina_ememoa_fixed_init, .shutdown = &eina_ememoa_fixed_shutdown, .realloc = &eina_ememoa_fixed_realloc, @@ -139,3 +140,5 @@ Eina_Mempool_Backend mp_backend = { .garbage_collect = &eina_ememoa_fixed_gc, .statistics = &eina_ememoa_fixed_statistics }; + +EINA_MODULE("ememoa_fixed", "mp", NULL, &mp_backend); diff --git a/legacy/eina/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c b/legacy/eina/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c index c175e2ce92..c424663f50 100644 --- a/legacy/eina/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c +++ b/legacy/eina/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c @@ -29,6 +29,7 @@ #include #include "eina_types.h" +#include "eina_module.h" #include "eina_private.h" typedef struct _Eina_Ememoa_Unknown_Size_Mempool Eina_Ememoa_Unknown_Size_Mempool; @@ -136,7 +137,7 @@ eina_ememoa_unknown_size_shutdown(void *data) free(efm); } -Eina_Mempool_Backend mp_backend = { +static Eina_Mempool_Backend mp_backend = { .init = &eina_ememoa_unknown_size_init, .shutdown = &eina_ememoa_unknown_size_shutdown, .realloc = &eina_ememoa_unknown_size_realloc, @@ -146,3 +147,4 @@ Eina_Mempool_Backend mp_backend = { .statistics = &eina_ememoa_unknown_size_statistics }; +EINA_MODULE("ememoa_unknown", "mp", NULL, &mp_backend); diff --git a/legacy/eina/src/modules/mp/pass_through/pass_through.c b/legacy/eina/src/modules/mp/pass_through/pass_through.c index bc5fd57119..78c6e81f5b 100644 --- a/legacy/eina/src/modules/mp/pass_through/pass_through.c +++ b/legacy/eina/src/modules/mp/pass_through/pass_through.c @@ -26,6 +26,7 @@ #include #include "eina_types.h" +#include "eina_module.h" #include "eina_private.h" static void * @@ -57,7 +58,7 @@ eina_pass_through_shutdown(__UNUSED__ void *data) { } -Eina_Mempool_Backend mp_backend = { +static Eina_Mempool_Backend mp_backend = { .init = &eina_pass_through_init, .shutdown = &eina_pass_through_shutdown, .realloc = &eina_pass_through_realloc, @@ -67,4 +68,5 @@ Eina_Mempool_Backend mp_backend = { .statistics = NULL }; +EINA_MODULE("pass_through", "mp", NULL, &mp_backend); diff --git a/legacy/eina/src/tests/Makefile.am b/legacy/eina/src/tests/Makefile.am index 0abb032cff..82cfb2375e 100644 --- a/legacy/eina/src/tests/Makefile.am +++ b/legacy/eina/src/tests/Makefile.am @@ -2,9 +2,13 @@ MAINTAINERCLEANFILES = Makefile.in benchdir = $(bindir) -AM_CPPFLAGS = \ --I$(top_srcdir)/src/lib \ --I$(top_srcdir)/src/include \ +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/include \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \ @CHECK_CFLAGS@ if EINA_ENABLE_TESTS @@ -24,6 +28,7 @@ eina_test_lalloc.c \ eina_test_hash.c \ eina_test_iterator.c \ eina_test_accessor.c \ +eina_test_module.c \ eina_test_list.c eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la diff --git a/legacy/eina/src/tests/eina_suite.c b/legacy/eina/src/tests/eina_suite.c index eeae6a94da..bc368c5d70 100644 --- a/legacy/eina/src/tests/eina_suite.c +++ b/legacy/eina/src/tests/eina_suite.c @@ -38,6 +38,7 @@ static const Eina_Test_Case etc[] = { { "List", eina_test_list }, { "Iterator", eina_test_iterator }, { "Accessor", eina_test_accessor }, + { "Module", eina_test_module }, { NULL, NULL } }; diff --git a/legacy/eina/src/tests/eina_suite.h b/legacy/eina/src/tests/eina_suite.h index 9f14a8a167..dfcb71564b 100644 --- a/legacy/eina/src/tests/eina_suite.h +++ b/legacy/eina/src/tests/eina_suite.h @@ -37,5 +37,6 @@ void eina_test_hash(TCase *tc); void eina_test_list(TCase *tc); void eina_test_iterator(TCase *tc); void eina_test_accessor(TCase *tc); +void eina_test_module(TCase *tc); #endif /* EINA_SUITE_H_ */ diff --git a/legacy/eina/src/tests/eina_test_module.c b/legacy/eina/src/tests/eina_test_module.c new file mode 100644 index 0000000000..24c769274d --- /dev/null +++ b/legacy/eina/src/tests/eina_test_module.c @@ -0,0 +1,114 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * 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.1 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 . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "eina_suite.h" +#include "eina_module.h" + +START_TEST(eina_module_init_shutdown) +{ + eina_module_init(); + eina_module_shutdown(); + eina_module_init(); + eina_module_init(); + eina_module_init(); + eina_module_shutdown(); + eina_module_init(); + eina_module_init(); + eina_module_root_add(PACKAGE_BUILD_DIR); + eina_module_shutdown(); + eina_module_shutdown(); + eina_module_shutdown(); + eina_module_shutdown(); +} +END_TEST + +static int i42 = 42; +static Eina_Module_Export static_test = { "simple", NULL, "test", &i42 }; +EAPI int stupid_test = 7; + +static Eina_Bool +_eina_module_test_cb(__UNUSED__ Eina_Module *m, __UNUSED__ void *data) +{ + return EINA_TRUE; +} + +START_TEST(eina_module_simple) +{ + Eina_Module_Group *gp; + Eina_Module *m; + Eina_List *list; + + eina_module_init(); + + eina_module_root_add(PACKAGE_BUILD_DIR"/src/tests"); + + gp = eina_module_group_new(); + fail_if(!gp); + + eina_module_path_register(gp, PACKAGE_BUILD_DIR"/src/modules", EINA_TRUE); + eina_module_path_register(gp, PACKAGE_BUILD_DIR"/src/lib", EINA_FALSE); + eina_module_path_register(gp, PACKAGE_BUILD_DIR"/src/lib", EINA_FALSE); + + eina_module_app_register(gp, "eina", "test", NULL); + eina_module_app_register(gp, "eina", "bench", "1.0.0"); + + eina_module_register(gp, &static_test); + + m = eina_module_new(gp, "unknown"); + fail_if(m); + + m = eina_module_new(gp, "simple"); + fail_if(!m); + + fail_if(eina_module_load(m) != EINA_TRUE); + + fprintf(stderr, "path: %s\n", eina_module_path_get(m)); + fail_if(strcmp("test", eina_module_export_type_get(m))); + fail_if(eina_module_export_version_get(m) != NULL); + fail_if(strcmp("simple", eina_module_export_name_get(m))); + fail_if(eina_module_export_object_get(m) != &i42); + fail_if(eina_module_symbol_get(m, "eina_list_init") != &eina_list_init); + + eina_module_unload(m); + eina_module_delete(m); + + list = eina_module_list_new(gp, _eina_module_test_cb, NULL); + eina_module_list_load(list); + eina_module_list_unload(list); + eina_module_list_delete(list); + + m = eina_module_new(gp, "simple"); + + eina_module_group_delete(gp); + + eina_module_shutdown(); +} +END_TEST + +void +eina_test_module(TCase *tc) +{ + tcase_add_test(tc, eina_module_init_shutdown); + tcase_add_test(tc, eina_module_simple); +}