2 * ion/ioncore/modules.c
4 * Copyright (c) Tuomo Valkonen 1999-2005.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
18 #include <libextl/readconfig.h>
22 #include "../version.h"
25 #ifndef CF_PRELOAD_MODULES
31 typedef void *dlhandle
;
34 static Rb_node modules
=NULL
;
37 static dlhandle
get_handle(const char *name
)
42 nd
=rb_find_key_n(modules
, name
, &found
);
49 static const char *get_name(dlhandle handle
)
53 rb_traverse(nd
, modules
){
55 return (const char *)(nd
->k
.key
);
61 static Rb_node
add_module(char *name
, dlhandle handle
)
63 return rb_insert(modules
, name
, handle
);
70 /*{{{ Module symbol access */
73 static void *get_module_symbol(dlhandle handle
,
74 const char *modulename
,
80 p
=scat(modulename
, name
);
92 static bool check_version(dlhandle handle
, const char *modulename
)
94 char *versionstr
=(char*)get_module_symbol(handle
, modulename
,
98 return (strcmp(versionstr
, ION_API_VERSION
)==0);
102 static bool call_init(dlhandle handle
, const char *modulename
)
104 bool (*initfn
)(void);
106 initfn
=(bool (*)())get_module_symbol(handle
, modulename
, "_init");
115 static void call_deinit(dlhandle handle
, const char *modulename
)
117 void (*deinitfn
)(void);
119 deinitfn
=(void (*)())get_module_symbol(handle
, modulename
, "_deinit");
132 bool ioncore_init_module_support()
135 return (modules
!=NULL
);
139 static int try_load(const char *file
, void *param
)
141 dlhandle handle
=NULL
;
142 const char *slash
, *dot
;
146 if(access(file
, F_OK
)!=0)
147 return EXTL_TRYCONFIG_NOTFOUND
;
149 slash
=strrchr(file
, '/');
150 dot
=strrchr(file
, '.');
158 warn(TR("Invalid module name."));
162 name
=ALLOC_N(char, dot
-slash
+1);
166 strncpy(name
, slash
, dot
-slash
);
167 name
[dot
-slash
]='\0';
169 if(get_handle(name
)){
170 warn_obj(file
, TR("The module is already loaded."));
174 handle
=dlopen(file
, RTLD_NOW
|RTLD_GLOBAL
);
177 warn_obj(file
, "%s", dlerror());
182 return EXTL_TRYCONFIG_OK
;
184 if(!check_version(handle
, name
)){
185 warn_obj(file
, TR("Module version information not found or "
186 "version mismatch. Refusing to use."));
190 mod
=add_module(name
, handle
);
195 if(!call_init(handle
, name
)){
196 warn_obj(file
, TR("Unable to initialise module %s."), name
);
201 return EXTL_TRYCONFIG_OK
;
208 return EXTL_TRYCONFIG_LOAD_FAILED
;
212 static bool do_load_module(const char *modname
)
216 retval
=extl_try_config(modname
, NULL
, (ExtlTryConfigFn
*)try_load
,
219 if(retval
==EXTL_TRYCONFIG_NOTFOUND
)
220 warn(TR("Unable to find '%s' on search path."), modname
);
222 return (retval
==EXTL_TRYCONFIG_OK
);
232 static void do_unload_module(Rb_node mod
)
234 char *name
=(char*)mod
->k
.key
;
235 dlhandle handle
=mod
->v
.val
;
237 call_deinit(handle
, name
);
244 void ioncore_unload_modules()
248 rb_traverse(mod
, modules
){
249 do_unload_module(mod
);
260 /*{{{ Static module support */
263 static bool call_init(WStaticModuleInfo
*handle
)
265 if(handle
->init
!=NULL
)
266 return handle
->init();
271 static void call_deinit(WStaticModuleInfo
*handle
)
273 if(handle
->deinit
!=NULL
)
278 extern WStaticModuleInfo ioncore_static_modules
[];
281 static bool do_load_module(const char *name
)
283 WStaticModuleInfo
*mod
;
285 for(mod
=ioncore_static_modules
; mod
->name
!=NULL
; mod
++){
286 if(strcmp(mod
->name
, name
)==0)
291 warn_obj(name
, TR("Unknown module."));
299 warn_obj(name
, TR("Unable to initialise module."));
309 void ioncore_unload_modules()
311 WStaticModuleInfo
*mod
;
313 for(mod
=ioncore_static_modules
; mod
->name
!=NULL
; mod
++){
322 bool ioncore_init_module_support()
338 * Attempt to load a C-side module.
341 bool ioncore_load_module(const char *modname
)
344 warn(TR("No module to load given."));
347 return do_load_module(modname
);