New plugins system
[opsoft.git] / silentbob / src / modding.cxx
blob6d780412cb8c0baa5112e3b97daba179a3a0e524
1 /*
2 * (c) Oleg Puchinin 2006
3 * graycardinalster@gmail.com
5 */
7 #include <dlfcn.h>
8 #include <head.h>
9 #include <mod.h>
10 #include <the_tt.h>
11 #include <dbg.h>
12 #include <bugs.h>
14 #define PLUGINS_MASK "find ~/plugins/ -name \"libplugin_*.so.*\""
16 typedef struct DArray *(*plug_init_t) (struct env_t *env);
18 mod_t * findPluginID (int ID)
20 int i;
21 mod_t * plug;
23 for (i = 0; i < ENV->modding->get_size (); i++) {
24 plug = (mod_t *) ENV->modding->get (i);
25 if (plug->ID == ID)
26 return plug;
29 return NULL;
32 char modding_optparse (int * i, int step)
34 int pos;
35 mod_t * plug;
36 mod_feature * f;
37 mod_language *
39 for (pos = 0; pos < ENV->modding->get_size (); pos++) {
40 plug = (mod_t *) ENV->modding->get (pos);
41 f = (mod_feature *) plug;
43 if (plug->Type == TYPE_FEATURE) {
44 f = (mod_feature *) plug;
46 if (step == 1) {
47 if (f->opt && f->opt (ENV->d_opts, i))
48 return 1;
51 if (step == 2) {
52 if (f->opt2 && f->opt2 (ENV->d_opts, i))
53 return 1;
59 return 0;
62 struct mod_language * find_language (char *S)
64 struct mod_language *pm = NULL;
65 int i;
67 //printf ("Plugins count : %i\n", ENV->modding->get_size ());
68 for (i = 0; i < ENV->modding->get_size (); i++) {
69 pm = (struct mod_language *) ENV->modding->get (i);
70 if (! pm)
71 continue;
73 if (pm->mod.Type != TYPE_LANGUAGE)
74 continue;
76 if (EQ (pm->language, S))
77 break;
80 if (i < ENV->modding->get_size ())
81 return pm;
83 return NULL;
86 void mods_info ()
88 struct mod_t *pm = NULL;
89 int i;
91 printf ("Available plugins: \n");
92 for (i = 0; i < ENV->modding->get_size (); i++) {
93 pm = (mod_t *) ENV->modding->get (i);
94 if (! pm)
95 continue;
97 if (! pm->short_info)
98 continue;
100 printf ("[%d]\t", pm->ID);
101 pm->short_info ();
102 printf ("\n");
106 void mod_plugin_info (int ID)
108 mod_t * plug;
110 plug = findPluginID (ID);
111 if (! plug) {
112 fprintf (stderr, "No such plugin [%d]", ID);
113 exit (1);
116 if (plug->long_info)
117 plug->long_info ();
120 FILE * mkctags_prepare ()
122 FILE * ofile;
124 if (SB_FLGET (SB_FLCTAGSAPPEND)) {
125 if (rename ("./tags", ENV->tmp_tags) < 0) {
126 fprintf (stderr, "$ rename: ./tags %s\n", ENV->tmp_tags);
127 perror ("rename");
128 exit (1);
130 ofile = fopen (ENV->tmp_tags, "a");
131 } else {
132 unlink (ENV->tmp_tags);
133 unlink ("./tags");
134 ofile = fopen (ENV->tmp_tags, "w");
137 if (ofile == NULL) {
138 fprintf (stderr, "fopen (\"%s\", \"w\")\n", ENV->tmp_tags);
139 perror ("fopen");
140 exit (1);
143 return ofile;
146 int modding_start (int i_cmd)
148 struct mod_language *pm = NULL;
149 struct tt_state_t * tt;
150 int i;
151 int size;
152 FILE * ofile = NULL;
154 pm = find_language (ENV->language);
155 if (pm == NULL || pm->the == NULL) {
156 assert (true, "Language plugin not found !\n");
157 return 1;
160 if (i_cmd == cmd_makectags)
161 ofile = mkctags_prepare ();
163 size = ENV->d_files->get_size ();
164 if (! size) {
165 switch (i_cmd) {
166 case cmd_makectags:
167 if (! pm->make_ctags)
168 return 2;
169 pm->make_ctags (NULL, ofile);
171 goto mod_out;
174 for (i = 0; i < size; i++) {
175 if (S_ISDIR (DLSTAT (ENV->d_files->get (i))->st_mode))
176 continue;
178 switch (i_cmd) {
179 case cmd_the_tt:
180 tt = CNEW (tt_state_t, 1);
181 memset (tt, 0, sizeof (struct tt_state_t));
182 tt->fileName = ENV->d_files->get (i);
184 if (! pm->the)
185 return 2;
187 pm->the (tt);
188 if (! SB_FLGET (SB_FLSIMULATE)) {
189 write (fileno (stdout), tt->result,
190 tt->resultSize);
191 printf ("\n");
194 free_tt_state (tt);
195 break;
197 case cmd_makectags:
198 if (! pm->make_ctags || !pm->the)
199 return 2;
201 pm->make_ctags (ENV->d_files->get (i), ofile);
202 break;
204 case cmd_call_tags:
205 if (! pm->call_tags)
206 return 2;
208 pm->call_tags (ENV->d_files->get (i));
209 break;
211 default:
212 bug_notsupported ();
213 i = size;
214 break;
218 mod_out:
219 if (ofile)
220 fclose (ofile);
222 if (i_cmd == cmd_makectags)
223 mk_tags ((char *) "tags", NULL);
225 return 0;
228 int modding_load_dir (char * path)
230 int i;
231 DArray * files;
233 files = Dfiles (path);
234 if (! files)
235 return -1;
237 for (i = 0; i < files->get_size (); i++) {
238 if (EQ (files->get (i), "."))
239 continue;
240 if (EQ (files->get (i), ".."))
241 continue;
242 modding_load_plugin (files->get (i), path);
245 files->foreach (free);
246 delete files;
247 return 0;
250 int modding_init ()
252 ENV->modding = new EArray(32);
253 modding_load_dir (ENV->home_plugins);
254 modding_load_dir (ENV->shared_plugins);
255 return 0;
258 int modding_load_plugin (char * name, char * path)
260 int n;
261 struct stat st;
262 char * s_dlerror;
263 void * lib_handle;
264 DArray *plug_list;
265 struct mod_t * sb_plugin;
266 plug_init_t func_handle;
267 char m_buf[512];
269 if (! path || ! name)
270 return -1;
272 if (*stail (path) == '/')
273 *stail(m_buf) = '\0';
275 m_buf[511] = 0;
276 snprintf (m_buf, 511, "%s/%s", path, name);
278 stat (m_buf, &st);
279 if (! S_ISREG (st.st_mode))
280 return -1;
282 dlerror ();
283 lib_handle = dlopen (m_buf, RTLD_NOW);
284 s_dlerror = (char *) dlerror ();
285 if (s_dlerror) {
286 bug_plugin (s_dlerror);
287 return -1;
290 func_handle = (plug_init_t) dlsym (lib_handle, "plugin_init");
291 s_dlerror = (char *) dlerror ();
292 if (s_dlerror) {
293 bug_plugin (s_dlerror);
294 return -1;
297 plug_list = func_handle (ENV);
298 if (plug_list == NULL)
299 return -1;
301 for (n = 0; n < plug_list->get_size (); n++) {
302 sb_plugin = (struct mod_t *) plug_list->get (n);
303 sb_plugin->mod_file = strdup (m_buf);
304 if (sb_plugin->short_info)
305 sb_plugin->ID = newPluginID ();
306 if (sb_plugin)
307 ENV->modding->add (LPCHAR (sb_plugin));
310 return 0;