-- init_compile_env
[silentbob2.git] / src / modding.cxx
blobc7abb8a61cd360d953472694aaa40dfce7be5b6e
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 typedef struct DArray *(*plug_init_t) (struct env_t *env);
16 mod_t * findPluginID (int ID)
18 int i;
19 mod_t * plug;
21 for (i = 0; i < ENV->modding->get_size (); i++) {
22 plug = (mod_t *) ENV->modding->get (i);
23 if (plug->ID == ID)
24 return plug;
27 return NULL;
30 char modding_optparse (int * i, int step)
32 int pos;
33 mod_t * plug;
35 for (pos = 0; pos < ENV->modding->get_size (); pos++) {
36 plug = (mod_t *) ENV->modding->get (pos);
38 if (step == 1) {
39 if (plug->opt && plug->opt (ENV->d_opts, i))
40 return 1;
43 if (step == 2) {
44 if (plug->opt2 && plug->opt2 (ENV->d_opts, i))
45 return 1;
49 return 0;
52 mod_t * find_language (char *S)
54 mod_t * plug;
55 int i;
57 for (i = 0; i < ENV->modding->get_size (); i++) {
58 plug = (mod_t *) ENV->modding->get (i);
59 if (! plug->language)
60 continue;
61 if (EQ (plug->language, S))
62 break;
65 if (i < ENV->modding->get_size ())
66 return plug;
68 return NULL;
71 void mods_short_info ()
73 struct mod_t *pm = NULL;
74 int i;
76 printf ("Available plugins: \n");
77 for (i = 0; i < ENV->modding->get_size (); i++) {
78 pm = (mod_t *) ENV->modding->get (i);
79 if (! pm)
80 continue;
82 if (! pm->short_info)
83 continue;
85 if (pm->internal)
86 continue;
88 printf ("[%d]\t", pm->ID);
89 pm->short_info ();
90 printf ("\n");
94 void plugins_viewer ()
96 char m_buf[256];
97 mod_t * plug;
98 int id;
100 while (true) {
101 printf ("\n");
102 mods_short_info ();
103 printf ("Plugin id: ");
104 fflush (stdout);
105 if (!fgets (m_buf, 255, stdin))
106 break;
108 chomp (m_buf);
109 if (EQ (m_buf, "q"))
110 exit (0);
112 id = atoi (m_buf);
113 plug = findPluginID (id);
114 if (! plug) {
115 printf ("Bad plugin ID !\n");
116 continue;
119 if (! plug->long_info) {
120 printf ("No plugin info !\n");
121 continue;
124 printf ("\n");
125 plug->long_info ();
126 printf ("\n<enter>\n");
127 fflush (stdout);
128 fgets (m_buf, 255, stdin);
129 printf ("\n");
133 void mod_plugin_info (int ID)
135 mod_t * plug;
137 plug = findPluginID (ID);
138 if (! plug) {
139 fprintf (stderr, "No such plugin [%d]", ID);
140 exit (1);
143 if (plug->long_info)
144 plug->long_info ();
147 FILE * mkctags_prepare ()
149 FILE * ofile;
151 if (SB_FLGET (SB_FLCTAGSAPPEND)) {
152 if (rename ("./tags", ENV->tmp_tags) < 0) {
153 fprintf (stderr, "$ rename: ./tags %s\n", ENV->tmp_tags);
154 perror ("rename");
155 exit (1);
157 ofile = fopen (ENV->tmp_tags, "a");
158 } else {
159 unlink (ENV->tmp_tags);
160 unlink ("./tags");
161 ofile = fopen (ENV->tmp_tags, "w");
164 if (ofile == NULL) {
165 fprintf (stderr, "fopen (\"%s\", \"w\")\n", ENV->tmp_tags);
166 perror ("fopen");
167 exit (1);
170 return ofile;
173 int modding_start (int i_cmd)
175 mod_t * plug;
176 struct tt_state_t * tt;
177 int i;
178 int size;
179 FILE * ofile = NULL;
181 // printf ("Find language plugin ...\n"); fflush (stdout);
182 plug = find_language (ENV->language);
183 if (plug == NULL)
184 return 1;
186 if (i_cmd == cmd_makectags)
187 ofile = mkctags_prepare ();
189 size = ENV->d_files->get_size ();
190 if (! size) {
191 switch (i_cmd) {
192 case cmd_makectags:
193 if (! plug->make_ctags)
194 return 2;
195 plug->make_ctags (NULL, ofile);
196 break;
198 case cmd_tags:
199 printf ("No such tags !\n");
200 exit (0);
201 break;
203 goto mod_out;
206 if (i_cmd == cmd_tags) {
207 if (! plug->print_tags)
208 return 2;
209 else {
210 plug->print_tags ();
211 return 0;
215 for (i = 0; i < size; i++) {
216 if (S_ISDIR (DLSTAT (ENV->d_files->get (i))->st_mode))
217 continue;
219 switch (i_cmd) {
220 case cmd_the_tt:
221 tt = CNEW (tt_state_t, 1);
222 memset (tt, 0, sizeof (struct tt_state_t));
223 tt->fileName = ENV->d_files->get (i);
225 if (! plug->the)
226 return 2;
228 plug->the (tt);
229 if (! SB_FLGET (SB_FLSIMULATE)) {
230 write (fileno (stdout), tt->result,
231 tt->resultSize);
232 printf ("\n");
235 free_tt_state (tt);
236 break;
238 case cmd_makectags:
239 if (! plug->make_ctags)
240 return 2;
242 plug->make_ctags (ENV->d_files->get (i), ofile);
243 break;
245 case cmd_call_tags:
246 if (! plug->call_tags)
247 return 2;
249 plug->call_tags (ENV->d_files->get (i));
250 break;
252 case cmd_file:
253 if (! plug->file)
254 return 2;
255 plug->file (ENV->d_files->get (i));
256 break;
258 default:
259 bug_notsupported ();
260 i = size;
261 break;
265 mod_out:
266 if (ofile)
267 fclose (ofile);
269 if (i_cmd == cmd_makectags)
270 mk_tags ((char *) "tags", NULL);
272 return 0;
275 int modding_load_dir (char * path)
277 int i;
278 DArray * files;
280 files = Dfiles (path);
281 if (! files)
282 return -1;
284 for (i = 0; i < files->get_size (); i++) {
285 if (EQ (files->get (i), "."))
286 continue;
287 if (EQ (files->get (i), ".."))
288 continue;
289 modding_load_plugin (files->get (i), path);
292 files->foreach (free);
293 delete files;
294 return 0;
297 int modding_init ()
299 ENV->modding = new EArray(32);
300 modding_load_dir (ENV->home_plugins);
301 modding_load_dir (ENV->shared_plugins);
302 return 0;
305 int modding_load_plugin (char * name, char * path)
307 int n;
308 struct stat st;
309 char * s_dlerror;
310 void * lib_handle;
311 DArray *plug_list;
312 struct mod_t * sb_plugin;
313 plug_init_t func_handle;
314 char m_buf[512];
316 if (! path || ! name)
317 return -1;
319 if (*stail (path) == '/')
320 *stail(m_buf) = '\0';
322 m_buf[511] = 0;
323 snprintf (m_buf, 511, "%s/%s", path, name);
325 stat (m_buf, &st);
326 if (! S_ISREG (st.st_mode))
327 return -1;
329 dlerror ();
330 lib_handle = dlopen (m_buf, RTLD_NOW);
331 s_dlerror = (char *) dlerror ();
332 if (s_dlerror) {
333 bug_plugin (s_dlerror);
334 return -1;
337 func_handle = (plug_init_t) dlsym (lib_handle, "plugin_init");
338 s_dlerror = (char *) dlerror ();
339 if (s_dlerror) {
340 bug_plugin (s_dlerror);
341 return -1;
344 plug_list = func_handle (ENV);
345 if (plug_list == NULL)
346 return -1;
348 for (n = 0; n < plug_list->get_size (); n++) {
349 sb_plugin = (struct mod_t *) plug_list->get (n);
350 sb_plugin->mod_file = strdup (m_buf);
351 if (sb_plugin->short_info)
352 sb_plugin->ID = newPluginID ();
353 if (sb_plugin)
354 ENV->modding->add (LPCHAR (sb_plugin));
357 return 0;