1 #include <stdio.h>
2 #include <string.h>
3
4 #include <stdlib.h> /* malloc */
5
6 /* lua includes */
7 #define LUA_CORE /* make sure that we don't try to import these functions */
8 #include <lua.h>
9 #include <lualib.h>
10 #include <lauxlib.h>
11
12 #include "node.h"
13 #include "context.h"
14 #include "support.h"
15 #include "luafuncs.h"
16 #include "path.h"
17 #include "mem.h"
18 #include "session.h"
19
build_stringlist(lua_State * L,struct HEAP * heap,struct STRINGLIST ** first,int table_index)20 void build_stringlist(lua_State *L, struct HEAP *heap, struct STRINGLIST **first, int table_index)
21 {
22 struct STRINGLIST *listitem;
23 const char *orgstr;
24 size_t len;
25
26 int i;
27 for(i = 1;; i++)
28 {
29 /* +1 value */
30 lua_rawgeti(L, table_index, i);
31
32 if(lua_type(L, -1) == LUA_TNIL)
33 break;
34
35 /* allocate and fix copy the string */
36 orgstr = lua_tolstring(L, -1, &len);
37 listitem = (struct STRINGLIST *)mem_allocate(heap, sizeof(struct STRINGLIST) + len + 1);
38 listitem->str = (const char *)(listitem+1);
39 listitem->len = len;
40 memcpy(listitem+1, orgstr, len+1);
41
42 /* add it to the list */
43 listitem->next = *first;
44 *first = listitem;
45
46 /* pop value */
47 lua_pop(L, 1);
48 }
49 }
50
51 /* value for deep walks */
52 static struct
53 {
54 void (*callback)(lua_State*, void*);
55 void *user;
56 } deepwalkinfo;
57
deep_walk_r(lua_State * L,int table_index)58 static void deep_walk_r(lua_State *L, int table_index)
59 {
60 int i;
61 for(i = 1;; i++)
62 {
63 /* +1 value */
64 lua_rawgeti(L, table_index, i);
65
66 if(lua_istable(L, -1))
67 deep_walk_r(L, lua_gettop(L));
68 else if(lua_type(L, -1) == LUA_TSTRING)
69 deepwalkinfo.callback(L, deepwalkinfo.user);
70 else if(lua_type(L, -1) == LUA_TNIL)
71 break;
72 else
73 {
74 /* other value */
75 luaL_error(L, "encountered something besides a string or a table");
76 }
77
78 /* pop +1 */
79 lua_pop(L, 1);
80 }
81 }
82
deep_walk(lua_State * L,int start,int stop,void (* callback)(lua_State *,void *),void * user)83 static void deep_walk(lua_State *L, int start, int stop, void (*callback)(lua_State*, void*), void *user)
84 {
85 int i;
86 deepwalkinfo.callback = callback;
87 deepwalkinfo.user = user;
88
89 for(i = start; i <= stop; i++)
90 {
91 if(lua_istable(L, i))
92 deep_walk_r(L, i);
93 else if(lua_type(L, i) == LUA_TSTRING)
94 {
95 lua_pushvalue(L, i);
96 deepwalkinfo.callback(L, user);
97 lua_pop(L, 1);
98 }
99 else
100 {
101 luaL_error(L, "encountered something besides a string or a table");
102 }
103 }
104 }
105
106 /* add_pseudo(string node) */
lf_add_pseudo(lua_State * L)107 int lf_add_pseudo(lua_State *L)
108 {
109 struct NODE *node;
110 struct CONTEXT *context;
111 int i;
112
113 if(lua_gettop(L) != 1)
114 luaL_error(L, "add_pseudo: incorrect number of arguments");
115
116 luaL_checktype(L, 1, LUA_TSTRING);
117
118 /* fetch contexst from lua */
119 context = context_get_pointer(L);
120
121 /* create the node */
122 i = node_create(&node, context->graph, lua_tostring(L,1), NULL, NULL);
123 if(i == NODECREATE_NOTNICE)
124 luaL_error(L, "add_pseudo: node '%s' is not nice", lua_tostring(L,1));
125 else if(i == NODECREATE_EXISTS)
126 luaL_error(L, "add_pseudo: node '%s' already exists", lua_tostring(L,1));
127 else if(i != NODECREATE_OK)
128 luaL_error(L, "add_pseudo: unknown error creating node '%s'", lua_tostring(L,1));
129
130 node_set_pseudo(node);
131 return 0;
132 }
133
134 /* add_output(string output, string other_output) */
lf_add_output(lua_State * L)135 int lf_add_output(lua_State *L)
136 {
137 struct NODE *output;
138 struct NODE *other_output;
139 struct CONTEXT *context;
140
141 if(lua_gettop(L) != 2)
142 luaL_error(L, "add_output: incorrect number of arguments");
143
144 luaL_checktype(L, 1, LUA_TSTRING);
145 luaL_checktype(L, 2, LUA_TSTRING);
146
147 context = context_get_pointer(L);
148
149 output = node_find(context->graph, lua_tostring(L,1));
150 if(!output)
151 luaL_error(L, "add_output: couldn't find node with name '%s'", lua_tostring(L,1));
152
153 other_output = node_get(context->graph, lua_tostring(L,2));
154 if(!other_output)
155 luaL_error(L, "add_output: couldn't find node with name '%s'", lua_tostring(L,2));
156
157 node_add_dependency_withnode(other_output, output);
158 node_set_pseudo(other_output);
159 return 0;
160 }
161
162 struct NODEATTRIB_CBINFO
163 {
164 struct NODE *node;
165 struct NODE *(*callback)(struct NODE*, const char *);
166 };
167
callback_node_attrib(lua_State * L,void * user)168 static void callback_node_attrib(lua_State *L, void *user)
169 {
170 struct NODEATTRIB_CBINFO *info = (struct NODEATTRIB_CBINFO *)user;
171 if(!info->callback(info->node, lua_tostring(L, -1)))
172 luaL_error(L, "could not add '%s' to '%s'", lua_tostring(L, -1), lua_tostring(L, 1));
173 }
174
175 /* add_dependency(string node, string dependency) */
add_node_attribute(lua_State * L,const char * funcname,struct NODE * (* callback)(struct NODE *,const char *))176 static int add_node_attribute(lua_State *L, const char *funcname, struct NODE *(*callback)(struct NODE*, const char *))
177 {
178 struct NODE *node;
179 struct CONTEXT *context;
180 int n = lua_gettop(L);
181 struct NODEATTRIB_CBINFO cbinfo;
182
183 if(n < 2)
184 luaL_error(L, "%s: to few arguments", funcname);
185
186 luaL_checktype(L, 1, LUA_TSTRING);
187
188 context = context_get_pointer(L);
189
190 node = node_find(context->graph, lua_tostring(L,1));
191 if(!node)
192 luaL_error(L, "%s: couldn't find node with name '%s'", funcname, lua_tostring(L,1));
193
194 /* seek deps */
195 cbinfo.node = node;
196 cbinfo.callback = callback;
197 deep_walk(L, 2, n, callback_node_attrib, &cbinfo);
198 return 0;
199 }
200
lf_add_dependency(lua_State * L)201 int lf_add_dependency(lua_State *L) { return add_node_attribute(L, "add_dependency", node_add_dependency); }
lf_add_constraint_shared(lua_State * L)202 int lf_add_constraint_shared(lua_State *L) { return add_node_attribute(L, "add_constraint_shared", node_add_constraint_shared); }
lf_add_constraint_exclusive(lua_State * L)203 int lf_add_constraint_exclusive(lua_State *L) { return add_node_attribute(L, "add_constraint_exclusive", node_add_constraint_exclusive); }
204
205 /* add_job(string output, string label, string command, ...) */
lf_add_job(lua_State * L)206 int lf_add_job(lua_State *L)
207 {
208 struct NODE *node;
209 struct CONTEXT *context;
210 struct NODEATTRIB_CBINFO cbinfo;
211 int i;
212
213 if(lua_gettop(L) < 3)
214 luaL_error(L, "add_job: too few arguments");
215
216 luaL_checktype(L, 1, LUA_TSTRING);
217 luaL_checktype(L, 2, LUA_TSTRING);
218 luaL_checktype(L, 3, LUA_TSTRING);
219
220 /* fetch contexst from lua */
221 context = context_get_pointer(L);
222
223 /* create the node */
224 i = node_create(&node, context->graph, lua_tostring(L,1), lua_tostring(L,2), lua_tostring(L,3));
225 if(i == NODECREATE_NOTNICE)
226 luaL_error(L, "add_job: node '%s' is not nice", lua_tostring(L,1));
227 else if(i == NODECREATE_EXISTS)
228 luaL_error(L, "add_job: node '%s' already exists", lua_tostring(L,1));
229 else if(i != NODECREATE_OK)
230 luaL_error(L, "add_job: unknown error creating node '%s'", lua_tostring(L,1));
231
232 /* seek deps */
233 cbinfo.node = node;
234 cbinfo.callback = node_add_dependency;
235 deep_walk(L, 4, lua_gettop(L), callback_node_attrib, &cbinfo);
236
237 return 0;
238 }
239
lf_set_touch(struct lua_State * L)240 int lf_set_touch(struct lua_State *L)
241 {
242 struct NODE *node;
243
244 if(lua_gettop(L) < 1)
245 luaL_error(L, "set_touch: too few arguments");
246
247 luaL_checktype(L, 1, LUA_TSTRING);
248
249 node = node_find(context_get_pointer(L)->graph, lua_tostring(L,1));
250 if(!node)
251 luaL_error(L, "set_touch: couldn't find node with name '%s'", lua_tostring(L,1));
252
253 node->touch = 1;
254 return 0;
255 }
256
257
lf_set_filter(struct lua_State * L)258 int lf_set_filter(struct lua_State *L)
259 {
260 struct NODE *node;
261 const char *str;
262 size_t len;
263
264 /* check the arguments */
265 if(lua_gettop(L) < 2)
266 luaL_error(L, "set_filter: too few arguments");
267
268 luaL_checktype(L, 1, LUA_TSTRING);
269 luaL_checktype(L, 2, LUA_TSTRING);
270
271 /* find the node */
272 node = node_find(context_get_pointer(L)->graph, lua_tostring(L,1));
273 if(!node)
274 luaL_error(L, "set_filter: couldn't find node with name '%s'", lua_tostring(L,1));
275
276 /* setup the string */
277 str = lua_tolstring(L, 2, &len);
278 node->filter = (char *)mem_allocate(node->graph->heap, len+1);
279 memcpy(node->filter, str, len+1);
280 return 0;
281 }
282
283 /* default_target(string filename) */
lf_default_target(lua_State * L)284 int lf_default_target(lua_State *L)
285 {
286 struct NODE *node;
287 struct CONTEXT *context;
288
289 int n = lua_gettop(L);
290 if(n != 1)
291 luaL_error(L, "default_target: incorrect number of arguments");
292 luaL_checktype(L, 1, LUA_TSTRING);
293
294 /* fetch context from lua */
295 context = context_get_pointer(L);
296
297 /* search for the node */
298 node = node_find(context->graph, lua_tostring(L,1));
299 if(!node)
300 luaL_error(L, "default_target: node '%s' not found", lua_tostring(L,1));
301
302 /* set target */
303 context_default_target(context, node);
304 return 0;
305 }
306
307 /* update_globalstamp(string filename) */
lf_update_globalstamp(lua_State * L)308 int lf_update_globalstamp(lua_State *L)
309 {
310 struct CONTEXT *context;
311 time_t file_stamp;
312
313 if(lua_gettop(L) < 1)
314 luaL_error(L, "update_globalstamp: too few arguments");
315 luaL_checktype(L, 1, LUA_TSTRING);
316
317 context = context_get_pointer(L);
318 file_stamp = file_timestamp(lua_tostring(L,1)); /* update global timestamp */
319
320 if(file_stamp > context->globaltimestamp)
321 context->globaltimestamp = file_stamp;
322
323 return 0;
324 }
325
326
327 /* loadfile(filename) */
lf_loadfile(lua_State * L)328 int lf_loadfile(lua_State *L)
329 {
330 if(lua_gettop(L) < 1)
331 luaL_error(L, "loadfile: too few arguments");
332 luaL_checktype(L, 1, LUA_TSTRING);
333
334 if(session.verbose)
335 printf("%s: reading script from '%s'\n", session.name, lua_tostring(L,1));
336
337 if(luaL_loadfile(L, lua_tostring(L,1)) != 0)
338 lua_error(L);
339 return 1;
340 }
341
342
343 /* ** */
debug_print_lua_value(lua_State * L,int i)344 static void debug_print_lua_value(lua_State *L, int i)
345 {
346 if(lua_type(L,i) == LUA_TNIL)
347 printf("nil");
348 else if(lua_type(L,i) == LUA_TSTRING)
349 printf("'%s'", lua_tostring(L,i));
350 else if(lua_type(L,i) == LUA_TNUMBER)
351 printf("%f", lua_tonumber(L,i));
352 else if(lua_type(L,i) == LUA_TBOOLEAN)
353 {
354 if(lua_toboolean(L,i))
355 printf("true");
356 else
357 printf("false");
358 }
359 else if(lua_type(L,i) == LUA_TTABLE)
360 {
361 printf("{...}");
362 }
363 else
364 printf("%p (%s (%d))", lua_topointer(L,i), lua_typename(L,lua_type(L,i)), lua_type(L,i));
365 }
366
367
368 /* error function */
lf_errorfunc(lua_State * L)369 int lf_errorfunc(lua_State *L)
370 {
371 int depth = 0;
372 int frameskip = 1;
373 lua_Debug frame;
374
375 if(session.report_color)
376 printf("\033[01;31m%s\033[00m\n", lua_tostring(L,-1));
377 else
378 printf("%s\n", lua_tostring(L,-1));
379
380 if(session.lua_backtrace)
381 {
382 printf("backtrace:\n");
383 while(lua_getstack(L, depth, &frame) == 1)
384 {
385 depth++;
386
387 lua_getinfo(L, "nlSf", &frame);
388
389 /* check for functions that just report errors. these frames just confuses more then they help */
390 if(frameskip && strcmp(frame.short_src, "[C]") == 0 && frame.currentline == -1)
391 continue;
392 frameskip = 0;
393
394 /* print stack frame */
395 printf(" %s(%d): %s %s\n", frame.short_src, frame.currentline, frame.name, frame.namewhat);
396
397 /* print all local variables for the frame */
398 if(session.lua_locals)
399 {
400 int i;
401 const char *name = 0;
402
403 i = 1;
404 while((name = lua_getlocal(L, &frame, i)) != NULL)
405 {
406 printf(" %s = ", name);
407 debug_print_lua_value(L,-1);
408 printf("\n");
409 lua_pop(L,1);
410 i++;
411 }
412
413 i = 1;
414 while((name = lua_getupvalue(L, -1, i)) != NULL)
415 {
416 printf(" upvalue #%d: %s ", i-1, name);
417 debug_print_lua_value(L, -1);
418 lua_pop(L,1);
419 i++;
420 }
421 }
422 }
423 }
424
425 return 1;
426 }
427
lf_panicfunc(lua_State * L)428 int lf_panicfunc(lua_State *L)
429 {
430 printf("%s: PANIC! I'm gonna segfault now\n", session.name);
431 *(int*)0 = 0;
432 return 0;
433 }
434
lf_mkdir(struct lua_State * L)435 int lf_mkdir(struct lua_State *L)
436 {
437 if(lua_gettop(L) < 1)
438 luaL_error(L, "mkdir: too few arguments");
439
440 if(!lua_isstring(L,1))
441 luaL_error(L, "mkdir: expected string");
442
443 if(file_createdir(lua_tostring(L,1)) == 0)
444 lua_pushnumber(L, 1);
445 else
446 lua_pushnil(L);
447 return 1;
448 }
449
450
lf_fileexist(struct lua_State * L)451 int lf_fileexist(struct lua_State *L)
452 {
453 if(lua_gettop(L) < 1)
454 luaL_error(L, "fileexist: too few arguments");
455
456 if(!lua_isstring(L,1))
457 luaL_error(L, "fileexist: expected string");
458
459 if(file_exist(lua_tostring(L,1)))
460 lua_pushnumber(L, 1);
461 else
462 lua_pushnil(L);
463 return 1;
464 }
465
lf_istable(lua_State * L)466 int lf_istable(lua_State *L)
467 {
468 if(lua_type(L,-1) == LUA_TTABLE)
469 lua_pushnumber(L, 1);
470 else
471 lua_pushnil(L);
472 return 1;
473 }
474
lf_isstring(lua_State * L)475 int lf_isstring(lua_State *L)
476 {
477 if(lua_type(L,-1) == LUA_TSTRING)
478 lua_pushnumber(L, 1);
479 else
480 lua_pushnil(L);
481 return 1;
482 }
483
484 /* TODO: remove this limit */
485 #define WALK_MAXDEPTH 32
486
487 struct WALKDATA
488 {
489 int index[WALK_MAXDEPTH];
490 int depth;
491 };
492
lf_table_walk_iter(struct lua_State * L)493 static int lf_table_walk_iter(struct lua_State *L)
494 {
495 struct WALKDATA *data;
496 int type;
497
498 /* 1: walk table 2: last value(ignore) */
499 lua_rawgeti(L, 1, 1); /* push 3: the walk data */
500 data = (struct WALKDATA *)lua_touserdata(L, -1);
501
502 /* 1: walk table 2: last value 3: walk data */
503 while(1)
504 {
505 data->index[data->depth]++;
506
507 /* .. 4: current table 5: current value */
508 lua_rawgeti(L, 1, data->depth+1); /* push 4: fetch table */
509 lua_rawgeti(L, -1, data->index[data->depth]); /* push 5: value in table */
510
511 type = lua_type(L, -1);
512
513 if(type == LUA_TTABLE)
514 {
515 data->depth++;
516 if(data->depth >= WALK_MAXDEPTH)
517 luaL_error(L, "max table depth exceeded");
518 data->index[data->depth] = 0;
519 lua_rawseti(L, 1, data->depth+1);
520 lua_pop(L, 1);
521 }
522 else if(type == LUA_TNIL)
523 {
524 /* pop table and nil value */
525 lua_pop(L, 2);
526 data->depth--;
527 if(data->depth == 0)
528 {
529 lua_pushnil(L);
530 return 1;
531 }
532 }
533 else if(type == LUA_TSTRING)
534 {
535 lua_pushvalue(L, 1); /* push the table stack again */
536 return 2;
537 }
538 else
539 luaL_error(L, "tablewalk: encountered strange value in tables");
540 }
541 }
542
543 /*
544 the walk table looks like this
545 t = {
546 [1] = walk data
547 [2] = table 1
548 [3] = table 2
549 [N] = table N
550 }
551 */
lf_table_walk(struct lua_State * L)552 int lf_table_walk(struct lua_State *L)
553 {
554 struct WALKDATA *data;
555
556 if(lua_gettop(L) != 1)
557 luaL_error(L, "table_walk: incorrect number of arguments");
558 luaL_checktype(L, 1, LUA_TTABLE);
559
560 /* 1: table to iterate over */
561 lua_pushcfunction(L, lf_table_walk_iter); /* 2: iterator function */
562 lua_createtable(L, 4, 0); /* 3: table stack */
563
564 data = (struct WALKDATA *)lua_newuserdata(L, sizeof(struct WALKDATA));
565 data->depth = 1;
566 data->index[data->depth] = 0;
567 lua_rawseti(L, 3, 1);
568
569 lua_pushvalue(L, 1);
570 lua_rawseti(L, 3, 2);
571 lua_pushnil(L);
572
573 return 3;
574 }
575
576 /* does a deep copy of a table */
table_deepcopy_r(struct lua_State * L)577 static int table_deepcopy_r(struct lua_State *L)
578 {
579 size_t s;
580
581 /* 1: table to copy, 2: new table */
582 s = lua_objlen(L, -1);
583 lua_createtable(L, 0, s);
584
585 /* 3: iterator */
586 lua_pushnil(L);
587 while(lua_next(L, -3))
588 {
589 /* 4: value */
590 if(lua_istable(L, -1))
591 {
592 table_deepcopy_r(L); /* 5: new table */
593 lua_pushvalue(L, -3); /* 6: key */
594 lua_pushvalue(L, -2); /* 7: value */
595 lua_settable(L, -6); /* pops 6 and 7 */
596 lua_pop(L, 1); /* pops 5 */
597 }
598 else
599 {
600 lua_pushvalue(L, -2); /* 5: key */
601 lua_pushvalue(L, -2); /* 6: value */
602 lua_settable(L, -5); /* pops 5 and 6 */
603 }
604
605 /* pops 4 */
606 lua_pop(L, 1);
607 }
608
609
610 /* transfer the meta table */
611 if(lua_getmetatable(L, -2))
612 lua_setmetatable(L, -2);
613
614 return 1;
615 }
616
lf_table_deepcopy(struct lua_State * L)617 int lf_table_deepcopy(struct lua_State *L)
618 {
619 if(lua_gettop(L) != 1)
620 luaL_error(L, "table_deepcopy: incorrect number of arguments");
621 luaL_checktype(L, 1, LUA_TTABLE);
622
623 return table_deepcopy_r(L);
624 }
625
626 static int flatten_index;
627
628 /* flattens a table into a simple table with strings */
lf_table_flatten_r(struct lua_State * L,int table_index)629 static int lf_table_flatten_r(struct lua_State *L, int table_index)
630 {
631 /* +1: iterator */
632 lua_pushnil(L);
633 while(lua_next(L, table_index))
634 {
635 /* +2: value */
636 if(lua_istable(L, -1))
637 lf_table_flatten_r(L, lua_gettop(L));
638 else if(lua_type(L, -1) == LUA_TSTRING)
639 {
640 lua_pushnumber(L, flatten_index); /* +3: key */
641 lua_pushvalue(L, -2); /* +4: value */
642 lua_settable(L, 2); /* pops +3 and +4 */
643
644 flatten_index++;
645 }
646 else
647 {
648 /* other value */
649 luaL_error(L, "encountered something besides a string or a table");
650 }
651
652 /* pops +2 */
653 lua_pop(L, 1);
654 }
655
656 return 1;
657 }
658
lf_table_flatten(struct lua_State * L)659 int lf_table_flatten(struct lua_State *L)
660 {
661 size_t s;
662
663 if(lua_gettop(L) != 1)
664 luaL_error(L, "table_flatten: incorrect number of arguments");
665 luaL_checktype(L, 1, LUA_TTABLE);
666
667 /* 1: table to copy, 2: new table */
668 s = lua_objlen(L, -1);
669 flatten_index = 1;
670 lua_createtable(L, 0, s);
671 lf_table_flatten_r(L, 1);
672 return 1;
673 }
674
675 static char string_buffer[1024*4];
676
lf_table_tostring(struct lua_State * L)677 int lf_table_tostring(struct lua_State *L)
678 {
679 /* 1: table 2: prefix, 3: postfix */
680 size_t prefix_len, postfix_len;
681 size_t total_len = 0;
682 size_t item_len = 0;
683 const char *prefix;
684 const char *postfix;
685 char *buffer;
686 char *current;
687 const char *item;
688
689 if(lua_gettop(L) != 3)
690 luaL_error(L, "table_tostring: incorrect number of arguments");
691
692 luaL_checktype(L, 1, LUA_TTABLE);
693
694 prefix = lua_tolstring(L, 2, &prefix_len);
695 postfix = lua_tolstring(L, 3, &postfix_len);
696
697 /* first, figure out the total size */
698
699 /* 4: iterator */
700 lua_pushnil(L);
701 while(lua_next(L, 1))
702 {
703 /* 5: value */
704 if(lua_type(L, -1) == LUA_TSTRING)
705 {
706 lua_tolstring(L, -1, &item_len);
707 total_len += prefix_len+item_len+postfix_len;
708 }
709
710 /* pops 5 */
711 lua_pop(L, 1);
712 }
713
714 /* now allocate the buffer and start building the complete string */
715 if(total_len < sizeof(string_buffer))
716 buffer = string_buffer;
717 else
718 buffer = malloc(total_len);
719
720 current = buffer;
721
722 /* 4: iterator */
723 lua_pushnil(L);
724 while(lua_next(L, 1))
725 {
726 /* 5: value */
727 if(lua_type(L, -1) == LUA_TSTRING)
728 {
729 item = lua_tolstring(L, -1, &item_len);
730 memcpy(current, prefix, prefix_len); current += prefix_len;
731 memcpy(current, item, item_len); current += item_len;
732 memcpy(current, postfix, postfix_len); current += postfix_len;
733 }
734
735 /* pops 5 */
736 lua_pop(L, 1);
737 }
738
739 /* push the new string onto the stack and clean up */
740 lua_pushlstring(L, buffer, total_len);
741 if(buffer != string_buffer)
742 free(buffer);
743
744 return 1;
745 }
746
lf_loadplugin(struct lua_State * L)747 int lf_loadplugin(struct lua_State *L)
748 {
749 PLUGINFUNC func;
750 if(lua_gettop(L) != 1)
751 luaL_error(L, "loadplugin: incorrect number of arguments");
752 luaL_checktype(L, 1, LUA_TSTRING);
753
754 func = plugin_load(lua_tostring(L, 1));
755 if(!func)
756 luaL_error(L, "loadplugin: error loading plugin");
757
758 lua_settop(L, 0);
759 if((*func)(L) != 0)
760 luaL_error(L, "loadplugin: error initing plugin");
761
762 return 0;
763 }
764