1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * lt-ext-module.c
4 * Copyright (C) 2011-2012 Akira TAGOH
5 *
6 * Authors:
7 * Akira TAGOH <akira@tagoh.org>
8 *
9 * You may distribute under the terms of either the GNU
10 * Lesser General Public License or the Mozilla Public
11 * License, as specified in the README file.
12 */
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
17 #include <ctype.h>
18 #if HAVE_DIRENT_H
19 #include <dirent.h>
20 #endif
21 #if HAVE_DLFCN_H
22 #include <dlfcn.h>
23 #endif
24 #if HAVE_LIBGEN_H
25 #include <libgen.h>
26 #endif
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "lt-mem.h"
32 #include "lt-messages.h"
33 #include "lt-ext-module-data.h"
34 #include "lt-ext-module.h"
35 #include "lt-ext-module-private.h"
36 #include "lt-lock.h"
37 #include "lt-utils.h"
38
39
40 /**
41 * SECTION: lt-ext-module
42 * @Short_Description: A module class to extend features in #lt_extension_t.
43 * @Title: Module - Accessor
44 *
45 * This class provides functionality to extend features in #lt_extension_t,
46 * such as validating tags more strictly.
47 */
48 struct _lt_ext_module_t {
49 lt_mem_t parent;
50 char *name;
51 lt_pointer_t module;
52 const lt_ext_module_funcs_t *funcs;
53 };
54
55 typedef struct _lt_ext_default_data_t {
56 lt_ext_module_data_t parent;
57 lt_string_t *tags;
58 } lt_ext_default_data_t;
59
60 static lt_ext_module_data_t *_lt_ext_default_create_data (void);
61 static lt_bool_t _lt_ext_default_precheck_tag(lt_ext_module_data_t *data,
62 const lt_tag_t *tag,
63 lt_error_t **error);
64 static lt_bool_t _lt_ext_default_parse_tag (lt_ext_module_data_t *data,
65 const char *subtag,
66 lt_error_t **error);
67 static char *_lt_ext_default_get_tag (lt_ext_module_data_t *data);
68 static lt_bool_t _lt_ext_default_validate_tag(lt_ext_module_data_t *data);
69 static lt_ext_module_data_t *_lt_ext_eaw_create_data (void);
70 static lt_bool_t _lt_ext_eaw_precheck_tag (lt_ext_module_data_t *data,
71 const lt_tag_t *tag,
72 lt_error_t **error);
73 static lt_bool_t _lt_ext_eaw_parse_tag (lt_ext_module_data_t *data,
74 const char *subtag,
75 lt_error_t **error);
76 static char *_lt_ext_eaw_get_tag (lt_ext_module_data_t *data);
77 static lt_bool_t _lt_ext_eaw_validate_tag (lt_ext_module_data_t *data);
78
79 #if !ENABLE_MODULE
80 extern const lt_ext_module_funcs_t *LT_MODULE_SYMBOL_ (lt_module_ext_t, get_funcs) (void);
81 extern const lt_ext_module_funcs_t *LT_MODULE_SYMBOL_ (lt_module_ext_u, get_funcs) (void);
82 #endif
83
84 static lt_ext_module_t *__lt_ext_modules[LT_MAX_EXT_MODULES + 1];
85 static lt_ext_module_t *__lt_ext_default_handler;
86 static lt_bool_t __lt_ext_module_initialized = FALSE;
87 static const lt_ext_module_funcs_t __default_funcs = {
88 NULL,
89 _lt_ext_default_create_data,
90 _lt_ext_default_precheck_tag,
91 _lt_ext_default_parse_tag,
92 _lt_ext_default_get_tag,
93 _lt_ext_default_validate_tag,
94 };
95 static const lt_ext_module_funcs_t __empty_and_wildcard_funcs = {
96 NULL,
97 _lt_ext_eaw_create_data,
98 _lt_ext_eaw_precheck_tag,
99 _lt_ext_eaw_parse_tag,
100 _lt_ext_eaw_get_tag,
101 _lt_ext_eaw_validate_tag,
102 };
103 LT_LOCK_DEFINE_STATIC (extmod);
104
105 /*< private >*/
106 static void
_lt_ext_default_destroy_data(lt_pointer_t data)107 _lt_ext_default_destroy_data(lt_pointer_t data)
108 {
109 lt_ext_default_data_t *d = data;
110
111 lt_string_unref(d->tags);
112 }
113
114 static lt_ext_module_data_t *
_lt_ext_default_create_data(void)115 _lt_ext_default_create_data(void)
116 {
117 lt_ext_module_data_t *retval = lt_ext_module_data_new(sizeof (lt_ext_default_data_t),
118 _lt_ext_default_destroy_data);
119
120 if (retval) {
121 lt_ext_default_data_t *data = (lt_ext_default_data_t *)retval;
122
123 data->tags = lt_string_new(NULL);
124 }
125
126 return retval;
127 }
128
129 static lt_bool_t
_lt_ext_default_precheck_tag(lt_ext_module_data_t * data,const lt_tag_t * tag,lt_error_t ** error)130 _lt_ext_default_precheck_tag(lt_ext_module_data_t *data,
131 const lt_tag_t *tag,
132 lt_error_t **error)
133 {
134 return TRUE;
135 }
136
137 static lt_bool_t
_lt_ext_default_parse_tag(lt_ext_module_data_t * data,const char * subtag,lt_error_t ** error)138 _lt_ext_default_parse_tag(lt_ext_module_data_t *data,
139 const char *subtag,
140 lt_error_t **error)
141 {
142 lt_ext_default_data_t *d = (lt_ext_default_data_t *)data;
143
144 if (lt_string_length(d->tags) > 0)
145 lt_string_append_printf(d->tags, "-%s", subtag);
146 else
147 lt_string_append(d->tags, subtag);
148
149 return TRUE;
150 }
151
152 static char *
_lt_ext_default_get_tag(lt_ext_module_data_t * data)153 _lt_ext_default_get_tag(lt_ext_module_data_t *data)
154 {
155 lt_ext_default_data_t *d = (lt_ext_default_data_t *)data;
156
157 return strdup(lt_string_value(d->tags));
158 }
159
160 static lt_bool_t
_lt_ext_default_validate_tag(lt_ext_module_data_t * data)161 _lt_ext_default_validate_tag(lt_ext_module_data_t *data)
162 {
163 return TRUE;
164 }
165
166 static void
_lt_ext_eaw_destroy_data(lt_pointer_t data)167 _lt_ext_eaw_destroy_data(lt_pointer_t data)
168 {
169 }
170
171 static lt_ext_module_data_t *
_lt_ext_eaw_create_data(void)172 _lt_ext_eaw_create_data(void)
173 {
174 lt_ext_module_data_t *retval = lt_ext_module_data_new(sizeof (lt_ext_module_data_t),
175 _lt_ext_eaw_destroy_data);
176
177 return retval;
178 }
179
180 static lt_bool_t
_lt_ext_eaw_precheck_tag(lt_ext_module_data_t * data,const lt_tag_t * tag,lt_error_t ** error)181 _lt_ext_eaw_precheck_tag(lt_ext_module_data_t *data,
182 const lt_tag_t *tag,
183 lt_error_t **error)
184 {
185 /* not allowed to process any extensions */
186
187 return FALSE;
188 }
189
190 static lt_bool_t
_lt_ext_eaw_parse_tag(lt_ext_module_data_t * data,const char * subtag,lt_error_t ** error)191 _lt_ext_eaw_parse_tag(lt_ext_module_data_t *data,
192 const char *subtag,
193 lt_error_t **error)
194 {
195 /* not allowed to add any tags */
196
197 return FALSE;
198 }
199
200 static char *
_lt_ext_eaw_get_tag(lt_ext_module_data_t * data)201 _lt_ext_eaw_get_tag(lt_ext_module_data_t *data)
202 {
203 return strdup("");
204 }
205
206 static lt_bool_t
_lt_ext_eaw_validate_tag(lt_ext_module_data_t * data)207 _lt_ext_eaw_validate_tag(lt_ext_module_data_t *data)
208 {
209 return TRUE;
210 }
211
212 #if ENABLE_MODULE
213 static lt_bool_t
lt_ext_module_load(lt_ext_module_t * module)214 lt_ext_module_load(lt_ext_module_t *module)
215 {
216 lt_bool_t retval = FALSE;
217 lt_string_t *fullname = lt_string_new(NULL);
218 char *filename = lt_strdup_printf("liblangtag-ext-%s." LT_MODULE_SUFFIX,
219 module->name);
220 char *path_list, *p, *s, *path;
221 const char *env = lt_getenv("LANGTAG_EXT_MODULE_PATH");
222 size_t len;
223
224 if (!env) {
225 path_list = strdup(
226 #ifdef ENABLE_DEBUG
227 BUILDDIR LT_DIR_SEPARATOR_S "extensions" LT_SEARCHPATH_SEPARATOR_S
228 BUILDDIR LT_DIR_SEPARATOR_S "extensions" LT_DIR_SEPARATOR_S ".libs" LT_SEARCHPATH_SEPARATOR_S
229 #endif
230 LANGTAG_EXT_MODULE_PATH);
231 } else {
232 path_list = strdup(env);
233 }
234
235 s = path_list;
236 do {
237 if (!s)
238 break;
239 p = strchr(s, LT_SEARCHPATH_SEPARATOR);
240 if (p == s) {
241 s++;
242 continue;
243 }
244 path = s;
245 if (p) {
246 *p = 0;
247 p++;
248 }
249 s = p;
250 while (*path && isspace((int)*path))
251 path++;
252 len = strlen(path);
253 while (len > 0 && isspace((int)path[len - 1]))
254 len--;
255 path[len] = 0;
256 if (path[0] != 0) {
257 lt_string_clear(fullname);
258 lt_string_append_filename(fullname, path, filename, NULL);
259 module->module = dlopen(lt_string_value(fullname),
260 RTLD_LAZY|RTLD_LOCAL);
261 if (module->module) {
262 lt_pointer_t func;
263
264 lt_mem_add_ref(&module->parent, module->module,
265 (lt_destroy_func_t)dlclose);
266 func = dlsym(module->module, "module_get_version");
267 if (!func) {
268 lt_warning("%s", dlerror());
269 break;
270 }
271 if (((lt_ext_module_version_func_t)func)() != LT_EXT_MODULE_VERSION) {
272 lt_warning("`%s' isn't satisfied the required module version.",
273 filename);
274 break;
275 }
276 func = dlsym(module->module, "module_get_funcs");
277 if (!func) {
278 lt_warning("%s", dlerror());
279 break;
280 }
281 if (!(module->funcs = ((lt_ext_module_get_funcs_func_t)func)())) {
282 lt_warning("No function table for `%s'",
283 filename);
284 break;
285 }
286 lt_debug(LT_MSGCAT_MODULE,
287 "Loading the external extension handler module: %s",
288 lt_string_value(fullname));
289 retval = TRUE;
290 }
291 }
292 } while (1);
293 if (!retval)
294 lt_warning("No such modules: %s", module->name);
295
296 lt_string_unref(fullname);
297 free(filename);
298 free(path_list);
299
300 return retval;
301 }
302 #endif /* ENABLE_MODULE */
303
304 static lt_ext_module_t *
lt_ext_module_new_with_data(const char * name,const lt_ext_module_funcs_t * funcs)305 lt_ext_module_new_with_data(const char *name,
306 const lt_ext_module_funcs_t *funcs)
307 {
308 lt_ext_module_t *retval;
309
310 lt_return_val_if_fail (name != NULL, NULL);
311 lt_return_val_if_fail (funcs != NULL, NULL);
312
313 retval = lt_mem_alloc_object(sizeof (lt_ext_module_t));
314 if (retval) {
315 retval->name = strdup(name);
316 lt_mem_add_ref(&retval->parent, retval->name,
317 (lt_destroy_func_t)free);
318 retval->funcs = funcs;
319
320 lt_debug(LT_MSGCAT_MODULE, "Loading the internal extension handler: %s", name);
321 }
322
323 return retval;
324 }
325
326 /*< protected >*/
327 lt_bool_t
lt_ext_module_validate_singleton(char singleton)328 lt_ext_module_validate_singleton(char singleton)
329 {
330 return (singleton >= '0' && singleton <= '9') ||
331 (singleton >= 'A' && singleton <= 'W') ||
332 (singleton >= 'Y' && singleton <= 'Z') ||
333 (singleton >= 'a' && singleton <= 'w') ||
334 (singleton >= 'y' && singleton <= 'z') ||
335 singleton == ' ' ||
336 singleton == '*';
337 }
338
339 int
lt_ext_module_singleton_char_to_int(char singleton_c)340 lt_ext_module_singleton_char_to_int(char singleton_c)
341 {
342 int retval = -1;
343
344 lt_return_val_if_fail (lt_ext_module_validate_singleton(singleton_c), -1);
345
346 if (singleton_c >= '0' && singleton_c <= '9') {
347 retval = singleton_c - '0';
348 } else if ((singleton_c >= 'a' && singleton_c <= 'z') ||
349 (singleton_c >= 'A' && singleton_c <= 'Z')) {
350 retval = tolower((int)singleton_c) - 'a' + 10;
351 } else if (singleton_c == ' ') {
352 retval = LT_MAX_EXT_MODULES - 2;
353 } else if (singleton_c == '*') {
354 retval = LT_MAX_EXT_MODULES - 1;
355 }
356
357 return retval;
358 }
359
360 char
lt_ext_module_singleton_int_to_char(int singleton)361 lt_ext_module_singleton_int_to_char(int singleton)
362 {
363 char retval;
364
365 lt_return_val_if_fail (singleton >= 0, 0);
366 lt_return_val_if_fail (singleton < LT_MAX_EXT_MODULES, 0);
367
368 if ((singleton - 10) < 0)
369 retval = singleton + '0';
370 else if (singleton == (LT_MAX_EXT_MODULES - 2))
371 retval = ' ';
372 else if (singleton == LT_MAX_EXT_MODULES - 1)
373 retval = '*';
374 else
375 retval = singleton - 10 + 'a';
376
377 return retval;
378 }
379
380 lt_ext_module_t *
lt_ext_module_new(const char * name)381 lt_ext_module_new(const char *name)
382 {
383 lt_ext_module_t *retval = NULL;
384
385 lt_return_val_if_fail (name != NULL, NULL);
386
387 #if ENABLE_MODULE
388 retval = lt_mem_alloc_object(sizeof (lt_ext_module_t));
389
390 if (retval) {
391 char *n = strdup(name);
392 char *filename = basename(n), *module = NULL;
393 static const char *prefix = "liblangtag-ext-";
394 static size_t prefix_len = 0;
395 char singleton_c;
396 int singleton;
397
398 if (prefix_len == 0)
399 prefix_len = strlen(prefix);
400
401 if (strncmp(filename, prefix, prefix_len) == 0) {
402 size_t len = strlen(&filename[prefix_len]);
403 size_t suffix_len = strlen(LT_MODULE_SUFFIX) + 1;
404
405 if (len > suffix_len &&
406 lt_strcmp0(&filename[prefix_len + len - suffix_len], "." LT_MODULE_SUFFIX) == 0) {
407 module = lt_strndup(&filename[prefix_len], len - suffix_len);
408 module[len - suffix_len] = 0;
409 }
410 }
411 if (!module)
412 module = strdup(filename);
413 retval->name = module;
414 lt_mem_add_ref(&retval->parent, retval->name,
415 (lt_destroy_func_t)free);
416
417 free(n);
418
419 if (!lt_ext_module_load(retval)) {
420 lt_ext_module_unref(retval);
421 return NULL;
422 }
423 singleton_c = lt_ext_module_get_singleton(retval);
424 if (singleton_c == ' ' ||
425 singleton_c == '*') {
426 lt_warning("Not allowed to override the internal handlers for special singleton.");
427 lt_ext_module_unref(retval);
428 return NULL;
429 }
430 singleton = lt_ext_module_singleton_char_to_int(singleton_c);
431 if (singleton < 0) {
432 lt_warning("Invalid singleton: `%c' - `%s'",
433 singleton_c,
434 retval->name);
435 lt_ext_module_unref(retval);
436 return NULL;
437 }
438 if (__lt_ext_modules[singleton]) {
439 lt_warning("Duplicate extension module: %s",
440 retval->name);
441 lt_ext_module_unref(retval);
442 return NULL;
443 }
444 __lt_ext_modules[singleton] = retval;
445 lt_mem_add_weak_pointer(&retval->parent,
446 (lt_pointer_t *)&__lt_ext_modules[singleton]);
447 }
448 #endif /* ENABLE_MODULE */
449
450 return retval;
451 }
452
453 lt_ext_module_t *
lt_ext_module_lookup(char singleton_c)454 lt_ext_module_lookup(char singleton_c)
455 {
456 int singleton = lt_ext_module_singleton_char_to_int(singleton_c);
457
458 lt_return_val_if_fail (singleton >= 0, NULL);
459 lt_return_val_if_fail (singleton < LT_MAX_EXT_MODULES, NULL);
460 lt_return_val_if_fail (__lt_ext_module_initialized, NULL);
461
462 if (!__lt_ext_modules[singleton])
463 return lt_ext_module_ref(__lt_ext_default_handler);
464
465 return lt_ext_module_ref(__lt_ext_modules[singleton]);
466 }
467
468 const char *
lt_ext_module_get_name(lt_ext_module_t * module)469 lt_ext_module_get_name(lt_ext_module_t *module)
470 {
471 lt_return_val_if_fail (module != NULL, NULL);
472
473 return module->name;
474 }
475
476 char
lt_ext_module_get_singleton(lt_ext_module_t * module)477 lt_ext_module_get_singleton(lt_ext_module_t *module)
478 {
479 lt_return_val_if_fail (module != NULL, 0);
480 lt_return_val_if_fail (module->funcs != NULL, 0);
481 lt_return_val_if_fail (module->funcs->get_singleton != NULL, 0);
482
483 return module->funcs->get_singleton();
484 }
485
486 lt_ext_module_data_t *
lt_ext_module_create_data(lt_ext_module_t * module)487 lt_ext_module_create_data(lt_ext_module_t *module)
488 {
489 lt_return_val_if_fail (module != NULL, NULL);
490 lt_return_val_if_fail (module->funcs != NULL, NULL);
491 lt_return_val_if_fail (module->funcs->create_data != NULL, NULL);
492
493 return module->funcs->create_data();
494 }
495
496 lt_bool_t
lt_ext_module_parse_tag(lt_ext_module_t * module,lt_ext_module_data_t * data,const char * subtag,lt_error_t ** error)497 lt_ext_module_parse_tag(lt_ext_module_t *module,
498 lt_ext_module_data_t *data,
499 const char *subtag,
500 lt_error_t **error)
501 {
502 lt_return_val_if_fail (module != NULL, FALSE);
503 lt_return_val_if_fail (data != NULL, FALSE);
504 lt_return_val_if_fail (subtag != NULL, FALSE);
505 lt_return_val_if_fail (module->funcs != NULL, FALSE);
506 lt_return_val_if_fail (module->funcs->parse_tag != NULL, FALSE);
507
508 return module->funcs->parse_tag(data, subtag, error);
509 }
510
511 char *
lt_ext_module_get_tag(lt_ext_module_t * module,lt_ext_module_data_t * data)512 lt_ext_module_get_tag(lt_ext_module_t *module,
513 lt_ext_module_data_t *data)
514 {
515 lt_return_val_if_fail (module != NULL, NULL);
516 lt_return_val_if_fail (data != NULL, NULL);
517 lt_return_val_if_fail (module->funcs != NULL, NULL);
518 lt_return_val_if_fail (module->funcs->get_tag != NULL, NULL);
519
520 return module->funcs->get_tag(data);
521 }
522
523 lt_bool_t
lt_ext_module_validate_tag(lt_ext_module_t * module,lt_ext_module_data_t * data)524 lt_ext_module_validate_tag(lt_ext_module_t *module,
525 lt_ext_module_data_t *data)
526 {
527 lt_return_val_if_fail (module != NULL, FALSE);
528 lt_return_val_if_fail (data != NULL, FALSE);
529 lt_return_val_if_fail (module->funcs != NULL, FALSE);
530 lt_return_val_if_fail (module->funcs->validate_tag != NULL, FALSE);
531
532 return module->funcs->validate_tag(data);
533 }
534
535 lt_bool_t
lt_ext_module_precheck_tag(lt_ext_module_t * module,lt_ext_module_data_t * data,const lt_tag_t * tag,lt_error_t ** error)536 lt_ext_module_precheck_tag(lt_ext_module_t *module,
537 lt_ext_module_data_t *data,
538 const lt_tag_t *tag,
539 lt_error_t **error)
540 {
541 lt_error_t *err = NULL;
542 lt_bool_t retval;
543
544 lt_return_val_if_fail (module != NULL, FALSE);
545 lt_return_val_if_fail (data != NULL, FALSE);
546 lt_return_val_if_fail (module->funcs != NULL, FALSE);
547 lt_return_val_if_fail (module->funcs->precheck_tag != NULL, FALSE);
548
549 retval = module->funcs->precheck_tag(data, tag, &err);
550 if (lt_error_is_set(err, LT_ERR_ANY)) {
551 if (error)
552 *error = lt_error_ref(err);
553 else
554 lt_error_print(err, LT_ERR_ANY);
555 lt_error_unref(err);
556 retval = FALSE;
557 }
558
559 return retval;
560 }
561
562 /*< public >*/
563 /**
564 * lt_ext_modules_load:
565 *
566 * Load all of the modules on the system, including the internal accessor.
567 * This has to be invoked before processing something with #lt_extension_t.
568 * or lt_db_initialize() does.
569 */
570 void
lt_ext_modules_load(void)571 lt_ext_modules_load(void)
572 {
573 #if ENABLE_MODULE
574 const char *env = lt_getenv("LANGTAG_EXT_MODULE_PATH");
575 char *path_list, *s, *p, *path;
576 size_t suffix_len = strlen(LT_MODULE_SUFFIX) + 1;
577
578 if (__lt_ext_module_initialized)
579 return;
580 if (!env) {
581 path_list = strdup(
582 #ifdef ENABLE_DEBUG
583 BUILDDIR LT_DIR_SEPARATOR_S "extensions" LT_SEARCHPATH_SEPARATOR_S
584 BUILDDIR LT_DIR_SEPARATOR_S "extensions" LT_DIR_SEPARATOR_S ".libs" LT_SEARCHPATH_SEPARATOR_S
585 #endif
586 LANGTAG_EXT_MODULE_PATH);
587 } else {
588 path_list = strdup(env);
589 }
590 s = path_list;
591 do {
592 DIR *dir;
593
594 if (!s)
595 break;
596 p = strchr(s, LT_SEARCHPATH_SEPARATOR);
597 if (s == p) {
598 s++;
599 continue;
600 }
601 path = s;
602 if (p) {
603 *p = 0;
604 p++;
605 }
606 s = p;
607
608 dir = opendir(path);
609 if (dir) {
610 struct dirent *dent, *p;
611
612 LT_LOCK (extmod);
613 while ((dent = readdir (dir))) {
614 size_t len = strlen (dent->d_name);
615 size_t dentlen = offsetof (struct dirent, d_name) + len + 1;
616
617 dentlen = ((dentlen + ALIGNOF_VOID_P - 1) & ~(ALIGNOF_VOID_P - 1));
618 p = (struct dirent *)malloc(dentlen);
619 if (!p) {
620 perror (__FUNCTION__);
621 LT_UNLOCK (extmod);
622 closedir(dir);
623 free(path_list);
624 return;
625 }
626 memcpy(p, dent, dentlen);
627 if (len > suffix_len &&
628 lt_strcmp0(&(p->d_name[len - suffix_len]),
629 "." LT_MODULE_SUFFIX) == 0) {
630 lt_ext_module_new(p->d_name);
631 }
632 free(p);
633 }
634 LT_UNLOCK (extmod);
635 closedir(dir);
636 }
637 } while (1);
638
639 free(path_list);
640 #else /* !ENABLE_MODULE */
641 const lt_ext_module_funcs_t *f;
642 int c;
643
644 #define REGISTER(_ext_) \
645 f = LT_MODULE_SYMBOL_ (lt_module_ext_##_ext_, get_funcs) (); \
646 c = lt_ext_module_singleton_char_to_int(f->get_singleton()); \
647 __lt_ext_modules[c] = lt_ext_module_new_with_data(#_ext_, f); \
648 lt_mem_add_weak_pointer(&__lt_ext_modules[c]->parent, \
649 (lt_pointer_t *)&__lt_ext_modules[c]);
650
651 REGISTER (t);
652 REGISTER (u);
653
654 #undef REGISTER
655 #endif /* ENABLE_MODULE */
656 __lt_ext_default_handler = lt_ext_module_new_with_data("default",
657 &__default_funcs);
658 lt_mem_add_weak_pointer(&__lt_ext_default_handler->parent,
659 (lt_pointer_t *)&__lt_ext_default_handler);
660 __lt_ext_modules[LT_MAX_EXT_MODULES - 2] = lt_ext_module_new_with_data("empty",
661 &__empty_and_wildcard_funcs);
662 lt_mem_add_weak_pointer(&__lt_ext_modules[LT_MAX_EXT_MODULES - 2]->parent,
663 (lt_pointer_t *)&__lt_ext_modules[LT_MAX_EXT_MODULES - 2]);
664 __lt_ext_modules[LT_MAX_EXT_MODULES - 1] = lt_ext_module_new_with_data("wildcard",
665 &__empty_and_wildcard_funcs);
666 lt_mem_add_weak_pointer(&__lt_ext_modules[LT_MAX_EXT_MODULES - 1]->parent,
667 (lt_pointer_t *)&__lt_ext_modules[LT_MAX_EXT_MODULES - 1]);
668 __lt_ext_module_initialized = TRUE;
669 }
670
671 /**
672 * lt_ext_modules_unload:
673 *
674 * Unload all of the modules already loaded.
675 */
676 void
lt_ext_modules_unload(void)677 lt_ext_modules_unload(void)
678 {
679 int i;
680
681 if (!__lt_ext_module_initialized)
682 return;
683 for (i = 0; i < LT_MAX_EXT_MODULES; i++) {
684 if (__lt_ext_modules[i])
685 lt_ext_module_unref(__lt_ext_modules[i]);
686 }
687 lt_ext_module_unref(__lt_ext_default_handler);
688 __lt_ext_module_initialized = FALSE;
689 }
690
691 /**
692 * lt_ext_module_ref:
693 * @module: a #lt_ext_module_t.
694 *
695 * Increases the reference count of @module.
696 *
697 * Returns: (transfer none): the same @module object.
698 */
699 lt_ext_module_t *
lt_ext_module_ref(lt_ext_module_t * module)700 lt_ext_module_ref(lt_ext_module_t *module)
701 {
702 lt_return_val_if_fail (module != NULL, NULL);
703
704 return lt_mem_ref(&module->parent);
705 }
706
707 /**
708 * lt_ext_module_unref:
709 * @module: a #lt_ext_module_t.
710 *
711 * Decreases the reference count of @module. when its reference count
712 * drops to 0, the object is finalized (i.e. its memory is freed).
713 */
714 void
lt_ext_module_unref(lt_ext_module_t * module)715 lt_ext_module_unref(lt_ext_module_t *module)
716 {
717 if (module)
718 lt_mem_unref(&module->parent);
719 }
720