2
* Smart Common Input Method
4
* Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this program; if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
* Boston, MA 02111-1307 USA
22
* $Id: scim_module.cpp,v 1.26 2005/05/24 12:22:51 suzhe Exp $
26
#define Uses_SCIM_MODULE
27
#define Uses_STL_ALGORITHM
28
#include "scim_private.h"
34
#include <sys/types.h>
40
typedef void (*ModuleInitFunc) (void);
41
typedef void (*ModuleExitFunc) (void);
43
struct Module::ModuleImpl
51
ModuleImpl () : handle (0), init (0), exit (0) { }
54
static std::vector <ModuleInitFunc> _scim_modules;
57
_scim_get_module_paths (std::vector <String> &paths, const String &type)
59
const char *module_path_env;
61
std::vector <String> module_paths;
62
std::vector <String>::iterator it;
66
module_path_env = getenv ("SCIM_MODULE_PATH");
69
module_paths.push_back (String (module_path_env));
71
module_paths.push_back (String (SCIM_MODULE_PATH));
73
// append version to the end of the paths
74
for (it = module_paths.begin (); it != module_paths.end (); ++it) {
77
tmp_dir = *it + String (SCIM_PATH_DELIM_STRING) +
78
String (SCIM_BINARY_VERSION) +
79
String (SCIM_PATH_DELIM_STRING) + type;
81
paths.push_back (tmp_dir);
83
tmp_dir = *it + String (SCIM_PATH_DELIM_STRING) + type;
84
paths.push_back (tmp_dir);
89
scim_get_module_list (std::vector <String>& mod_list, const String& type)
91
std::vector<String> paths;
92
_scim_get_module_paths (paths, type);
96
for (std::vector<String>::iterator i = paths.begin (); i!= paths.end (); ++i) {
97
DIR *dir = opendir (i->c_str ());
99
struct dirent *file = readdir (dir);
101
struct stat filestat;
102
String absfn = *i + String (SCIM_PATH_DELIM_STRING) + file->d_name;
103
stat (absfn.c_str (), &filestat);
104
if (S_ISREG (filestat.st_mode)) {
105
std::vector<String> vec;
106
scim_split_string_list (vec, String (file->d_name), '.');
107
mod_list.push_back (vec [0]);
109
file = readdir (dir);
114
std::sort (mod_list.begin (), mod_list.end ());
115
mod_list.erase (std::unique (mod_list.begin(), mod_list.end()), mod_list.end());
116
return mod_list.size ();
120
: m_impl (new ModuleImpl)
125
Module::Module (const String &name, const String &type)
126
: m_impl (new ModuleImpl)
140
_concatenate_ltdl_prefix (const String &name, const String &symbol)
142
String prefix (name);
144
for (size_t i=0; i<prefix.length (); i++)
145
if (!isalnum ((int)prefix[i]))
148
return prefix + String ("_LTX_") + symbol;
152
Module::load (const String &name, const String &type)
154
// If cannot unload original module (it's resident), then return false.
158
std::vector <String> paths;
159
std::vector <String>::iterator it;
163
lt_dlhandle new_handle = 0;
165
ModuleInitFunc new_init;
166
ModuleExitFunc new_exit;
168
_scim_get_module_paths (paths, type);
170
for (it = paths.begin (); it != paths.end (); ++it) {
171
module_path = *it + String (SCIM_PATH_DELIM_STRING) + name;
172
new_handle = lt_dlopenext (module_path.c_str ());
178
new_handle = lt_dlopenext (name.c_str ());
186
// Try to load the symbol scim_module_init
187
symbol = "scim_module_init";
188
new_init = (ModuleInitFunc) lt_dlsym (new_handle, symbol.c_str ());
190
// If symbol load failed, try to add LTX prefix and load again.
191
// This will occurred when name.la is missing.
193
symbol = _concatenate_ltdl_prefix (name, symbol);
194
new_init = (ModuleInitFunc) lt_dlsym (new_handle, symbol.c_str ());
196
// Failed again? Try to prepend a under score to the symbol name.
198
symbol.insert (symbol.begin (),'_');
199
new_init = (ModuleInitFunc) lt_dlsym (new_handle, symbol.c_str ());
203
// Could not load the module!
205
lt_dlclose (new_handle);
209
// Try to load the symbol scim_module_exit
210
symbol = "scim_module_exit";
211
new_exit = (ModuleExitFunc) lt_dlsym (new_handle, symbol.c_str ());
213
// If symbol load failed, try to add LTX prefix and load again.
214
// This will occurred when name.la is missing.
216
symbol = _concatenate_ltdl_prefix (name, symbol);
217
new_exit = (ModuleExitFunc) lt_dlsym (new_handle, symbol.c_str ());
219
// Failed again? Try to prepend a under score to the symbol name.
221
symbol.insert (symbol.begin (),'_');
222
new_exit = (ModuleExitFunc) lt_dlsym (new_handle, symbol.c_str ());
226
//Check if the module is already loaded.
227
if (std::find (_scim_modules.begin (), _scim_modules.end (), new_init)
228
!= _scim_modules.end ()) {
229
lt_dlclose (new_handle);
234
_scim_modules.push_back (new_init);
236
const lt_dlinfo *info = lt_dlgetinfo (new_handle);
238
m_impl->handle = new_handle;
239
m_impl->init = new_init;
240
m_impl->exit = new_exit;
241
m_impl->path = String (info->filename);
251
lt_dlclose (new_handle);
267
try { m_impl->exit (); } catch (...) { }
270
lt_dlclose (m_impl->handle);
272
std::vector <ModuleInitFunc>::iterator it =
273
std::find (_scim_modules.begin (), _scim_modules.end (), m_impl->init);
275
if (it != _scim_modules.end ())
276
_scim_modules.erase (it);
281
m_impl->path = String ();
282
m_impl->name = String ();
288
Module::make_resident () const
290
if (m_impl->handle) {
291
return lt_dlmakeresident (m_impl->handle) == 0;
297
Module::is_resident () const
299
if (m_impl->handle) {
300
return lt_dlisresident (m_impl->handle) == 1;
306
Module::valid () const
308
return (m_impl->handle && m_impl->init);
312
Module::get_path () const
318
Module::symbol (const String & sym) const
322
if (m_impl->handle) {
324
func = lt_dlsym (m_impl->handle, symbol.c_str ());
326
symbol = _concatenate_ltdl_prefix (m_impl->name, symbol);
327
func = lt_dlsym (m_impl->handle, symbol.c_str ());
329
symbol.insert (symbol.begin (), '_');
330
func = lt_dlsym (m_impl->handle, symbol.c_str ());
340
vi:ts=4:nowrap:ai:expandtab