+ Fixes
[opsoft.git] / silentbob / src / modding.cxx
blob5b9353a1a7b7364d2bb86535f857a847173e8c19
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;
37 for (pos = 0; pos < ENV->modding->get_size (); pos++) {
38 plug = (mod_t *) ENV->modding->get (pos);
40 if (step == 1) {
41 if (plug->opt && plug->opt (ENV->d_opts, i))
42 return 1;
45 if (step == 2) {
46 if (plug->opt2 && plug->opt2 (ENV->d_opts, i))
47 return 1;
51 return 0;
54 mod_t * find_language (char *S)
56 mod_t * plug;
57 int i;
59 for (i = 0; i < ENV->modding->get_size (); i++) {
60 plug = (mod_t *) ENV->modding->get (i);
61 if (! plug->language)
62 continue;
63 if (EQ (plug->language, S))
64 break;
67 if (i < ENV->modding->get_size ())
68 return plug;
70 return NULL;
73 void mods_short_info ()
75 struct mod_t *pm = NULL;
76 int i;
78 printf ("Available plugins: \n");
79 for (i = 0; i < ENV->modding->get_size (); i++) {
80 pm = (mod_t *) ENV->modding->get (i);
81 if (! pm)
82 continue;
84 if (! pm->short_info)
85 continue;
87 printf ("[%d]\t", pm->ID);
88 pm->short_info ();
89 printf ("\n");
93 void plugins_viewer ()
95 char m_buf[256];
96 mod_t * plug;
97 int id;
99 while (true) {
100 printf ("\n");
101 mods_short_info ();
102 printf ("Plugin id: ");
103 fflush (stdout);
104 if (!fgets (m_buf, 255, stdin))
105 break;
107 chomp (m_buf);
108 if (EQ (m_buf, "q"))
109 exit (0);
111 id = atoi (m_buf);
112 plug = findPluginID (id);
113 if (! plug) {
114 printf ("Bad plugin ID !\n");
115 continue;
118 if (! plug->long_info) {
119 printf ("No plugin info !\n");
120 continue;
123 printf ("\n");
124 plug->long_info ();
125 printf ("\n<enter>\n");
126 fflush (stdout);
127 fgets (m_buf, 255, stdin);
128 printf ("\n");
132 void mod_plugin_info (int ID)
134 mod_t * plug;
136 plug = findPluginID (ID);
137 if (! plug) {
138 fprintf (stderr, "No such plugin [%d]", ID);
139 exit (1);
142 if (plug->long_info)
143 plug->long_info ();
146 FILE * mkctags_prepare ()
148 FILE * ofile;
150 if (SB_FLGET (SB_FLCTAGSAPPEND)) {
151 if (rename ("./tags", ENV->tmp_tags) < 0) {
152 fprintf (stderr, "$ rename: ./tags %s\n", ENV->tmp_tags);
153 perror ("rename");
154 exit (1);
156 ofile = fopen (ENV->tmp_tags, "a");
157 } else {
158 unlink (ENV->tmp_tags);
159 unlink ("./tags");
160 ofile = fopen (ENV->tmp_tags, "w");
163 if (ofile == NULL) {
164 fprintf (stderr, "fopen (\"%s\", \"w\")\n", ENV->tmp_tags);
165 perror ("fopen");
166 exit (1);
169 return ofile;
172 int modding_start (int i_cmd)
174 mod_t * plug;
175 struct tt_state_t * tt;
176 int i;
177 int size;
178 FILE * ofile = NULL;
180 // printf ("Find language plugin ...\n"); fflush (stdout);
181 plug = find_language (ENV->language);
182 if (plug == NULL)
183 return 1;
185 if (i_cmd == cmd_makectags)
186 ofile = mkctags_prepare ();
188 size = ENV->d_files->get_size ();
189 if (! size) {
190 switch (i_cmd) {
191 case cmd_makectags:
192 if (! plug->make_ctags)
193 return 2;
194 plug->make_ctags (NULL, ofile);
195 break;
197 case cmd_tags:
198 printf ("No such tags !\n");
199 exit (0);
200 break;
202 goto mod_out;
205 if (i_cmd == cmd_tags) {
206 if (! plug->print_tags)
207 return 2;
208 else {
209 plug->print_tags ();
210 return 0;
214 for (i = 0; i < size; i++) {
215 if (S_ISDIR (DLSTAT (ENV->d_files->get (i))->st_mode))
216 continue;
218 switch (i_cmd) {
219 case cmd_the_tt:
220 tt = CNEW (tt_state_t, 1);
221 memset (tt, 0, sizeof (struct tt_state_t));
222 tt->fileName = ENV->d_files->get (i);
224 if (! plug->the)
225 return 2;
227 plug->the (tt);
228 if (! SB_FLGET (SB_FLSIMULATE)) {
229 write (fileno (stdout), tt->result,
230 tt->resultSize);
231 printf ("\n");
234 free_tt_state (tt);
235 break;
237 case cmd_makectags:
238 if (! plug->make_ctags)
239 return 2;
241 plug->make_ctags (ENV->d_files->get (i), ofile);
242 break;
244 case cmd_call_tags:
245 if (! plug->call_tags)
246 return 2;
248 plug->call_tags (ENV->d_files->get (i));
249 break;
251 case cmd_file:
252 if (! plug->file)
253 return 2;
254 plug->file (ENV->d_files->get (i));
255 break;
257 default:
258 bug_notsupported ();
259 i = size;
260 break;
264 mod_out:
265 if (ofile)
266 fclose (ofile);
268 if (i_cmd == cmd_makectags)
269 mk_tags ((char *) "tags", NULL);
271 return 0;
274 int modding_load_dir (char * path)
276 int i;
277 DArray * files;
279 files = Dfiles (path);
280 if (! files)
281 return -1;
283 for (i = 0; i < files->get_size (); i++) {
284 if (EQ (files->get (i), "."))
285 continue;
286 if (EQ (files->get (i), ".."))
287 continue;
288 modding_load_plugin (files->get (i), path);
291 files->foreach (free);
292 delete files;
293 return 0;
296 int modding_init ()
298 ENV->modding = new EArray(32);
299 modding_load_dir (ENV->home_plugins);
300 modding_load_dir (ENV->shared_plugins);
301 return 0;
304 int modding_load_plugin (char * name, char * path)
306 int n;
307 struct stat st;
308 char * s_dlerror;
309 void * lib_handle;
310 DArray *plug_list;
311 struct mod_t * sb_plugin;
312 plug_init_t func_handle;
313 char m_buf[512];
315 if (! path || ! name)
316 return -1;
318 if (*stail (path) == '/')
319 *stail(m_buf) = '\0';
321 m_buf[511] = 0;
322 snprintf (m_buf, 511, "%s/%s", path, name);
324 stat (m_buf, &st);
325 if (! S_ISREG (st.st_mode))
326 return -1;
328 dlerror ();
329 lib_handle = dlopen (m_buf, RTLD_NOW);
330 s_dlerror = (char *) dlerror ();
331 if (s_dlerror) {
332 bug_plugin (s_dlerror);
333 return -1;
336 func_handle = (plug_init_t) dlsym (lib_handle, "plugin_init");
337 s_dlerror = (char *) dlerror ();
338 if (s_dlerror) {
339 bug_plugin (s_dlerror);
340 return -1;
343 plug_list = func_handle (ENV);
344 if (plug_list == NULL)
345 return -1;
347 for (n = 0; n < plug_list->get_size (); n++) {
348 sb_plugin = (struct mod_t *) plug_list->get (n);
349 sb_plugin->mod_file = strdup (m_buf);
350 if (sb_plugin->short_info)
351 sb_plugin->ID = newPluginID ();
352 if (sb_plugin)
353 ENV->modding->add (LPCHAR (sb_plugin));
356 return 0;