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