]> jfr.im git - irc/evilnet/x3.git/blame - src/modules.c
Minor typo in previous commit where returning 0 when it should have been 1 from opser...
[irc/evilnet/x3.git] / src / modules.c
CommitLineData
d76ed9a9 1/* modules.c - Compiled-in module support
2 * Copyright 2002-2003 srvx Development Team
3 *
83ff05c3 4 * This file is part of x3.
d76ed9a9 5 *
d0f04f71 6 * x3 is free software; you can redistribute it and/or modify
d76ed9a9 7 * it under the terms of the GNU General Public License as published by
348683aa 8 * the Free Software Foundation; either version 3 of the License, or
d76ed9a9 9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
0b350353 21#ifdef WITH_PYTHON
22#include "Python.h"
23#endif
d76ed9a9 24#include "log.h"
25#include "modules.h"
26
27enum init_state {
28 UNINIT,
29 WORKING,
30 BROKEN,
31 INITED,
32 DONE
33};
34
35struct cmodule {
36 const char *name;
37 int (*init_func)(void);
38 int (*finalize_func)(void);
39 const char **deps;
40 enum init_state state;
41};
42
43#define WITH_MODULE(x) extern int x##_init(void); extern int x##_finalize(void); extern const char *x##_module_deps[];
44#include "modules-list.h"
45#undef WITH_MODULE
46
47static struct cmodule cmodules[] = {
48#define WITH_MODULE(x) { #x, x##_init, x##_finalize, x##_module_deps, UNINIT },
49#include "modules-list.h"
50#undef WITH_MODULE
51 /* Placeholder at end of array */
52 { NULL, NULL, NULL, NULL, UNINIT }
53};
54
55static int
56modules_bsearch(const void *a, const void *b) {
57 const char *key = a;
58 const struct cmodule *cmod = b;
59 return irccasecmp(key, cmod->name);
60}
61
62static int
63modules_qsort(const void *a, const void *b) {
64 const struct cmodule *ca = a, *cb = b;
65 return irccasecmp(ca->name, cb->name);
66}
67
68static int
69module_init(struct cmodule *cmod, int final) {
70 unsigned int ii;
71 struct cmodule *dep;
72
73 switch (cmod->state) {
74 case UNINIT: break;
75 case INITED: if (!final) return 1; break;
76 case DONE: return 1;
77 case BROKEN: return 0;
78 case WORKING:
79 log_module(MAIN_LOG, LOG_ERROR, "Tried to recursively enable code module %s.", cmod->name);
80 return 0;
81 }
82 cmod->state = WORKING;
83 for (ii=0; cmod->deps[ii]; ++ii) {
84 dep = bsearch(cmod->deps[ii], cmodules, ArrayLength(cmodules)-1, sizeof(cmodules[0]), modules_bsearch);
85 if (!dep) {
86 log_module(MAIN_LOG, LOG_ERROR, "Code module %s depends on unknown module %s.", cmod->name, cmod->deps[ii]);
87 cmod->state = BROKEN;
88 return 0;
89 }
90 if (!module_init(dep, final)) {
91 log_module(MAIN_LOG, LOG_ERROR, "Failed to initialize dependency %s of code module %s.", dep->name, cmod->name);
92 cmod->state = BROKEN;
93 return 0;
94 }
95 }
96 if (final) {
97 if (!cmod->finalize_func()) {
98 log_module(MAIN_LOG, LOG_ERROR, "Failed to finalize code module %s.", cmod->name);
99 cmod->state = BROKEN;
100 return 0;
101 }
102 cmod->state = DONE;
103 return 1;
104 } else {
105 if (!cmod->init_func()) {
106 log_module(MAIN_LOG, LOG_ERROR, "Failed to initialize code module %s.", cmod->name);
107 cmod->state = BROKEN;
108 return 0;
109 }
110 cmod->state = INITED;
111 return 1;
112 }
113}
114
115void
116modules_init(void) {
117 unsigned int ii;
118
119 qsort(cmodules, ArrayLength(cmodules)-1, sizeof(cmodules[0]), modules_qsort);
120 for (ii=0; cmodules[ii].name; ++ii) {
121 if (cmodules[ii].state != UNINIT) continue;
122 module_init(cmodules + ii, 0);
123 if (cmodules[ii].state != INITED) {
124 log_module(MAIN_LOG, LOG_WARNING, "Code module %s not properly initialized.", cmodules[ii].name);
125 }
126 }
127}
128
129void
130modules_finalize(void) {
131 unsigned int ii;
132
133 for (ii=0; cmodules[ii].name; ++ii) {
134 if (cmodules[ii].state != INITED) continue;
135 module_init(cmodules + ii, 1);
136 if (cmodules[ii].state != DONE) {
137 log_module(MAIN_LOG, LOG_WARNING, "Code module %s not properly finalized.", cmodules[ii].name);
138 }
139 }
140}