Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
2002beac004ad39f311937ca885d7a5a1f005877
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* SimGrid Lua bindings                                                     */
2
3 /* Copyright (c) 2010. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8 #include "simgrid_lua.h"
9
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
11
12 static lua_State *lua_maestro_state;
13
14 #define TASK_MODULE_NAME "simgrid.Task"
15 #define HOST_MODULE_NAME "simgrid.Host"
16 // Surf (bypass XML)
17 #define LINK_MODULE_NAME "simgrid.Link"
18 #define ROUTE_MODULE_NAME "simgrid.Route"
19 #define AS_MODULE_NAME "simgrid.AS"
20 #define TRACE_MODULE_NAME "simgrid.Trace"
21
22 static void stack_dump(const char *msg, lua_State *L);
23 static m_task_t check_task(lua_State *L, int index);
24 static void register_c_functions(lua_State *L);
25
26 /* ********************************************************************************* */
27 /*                            helper functions                                       */
28 /* ********************************************************************************* */
29
30 /**
31  * @brief Dumps the Lua stack
32  * @param msg a message to print
33  * @param L a Lua state
34  */
35 static void stack_dump(const char *msg, lua_State *L)
36 {
37   char buff[2048];
38   char *p = buff;
39   int i;
40   int top = lua_gettop(L);
41
42   fflush(stdout);
43   p += sprintf(p, "STACK(top=%d): ", top);
44
45   for (i = 1; i <= top; i++) {  /* repeat for each level */
46     int t = lua_type(L, i);
47     switch (t) {
48
49     case LUA_TSTRING:          /* strings */
50       p += sprintf(p, "`%s'", lua_tostring(L, i));
51       break;
52
53     case LUA_TBOOLEAN:         /* booleans */
54       p += sprintf(p, lua_toboolean(L, i) ? "true" : "false");
55       break;
56
57     case LUA_TNUMBER:          /* numbers */
58       p += sprintf(p, "%g", lua_tonumber(L, i));
59       break;
60
61     case LUA_TTABLE:
62       p += sprintf(p, "Table");
63       break;
64
65     default:                   /* other values */
66       p += sprintf(p, "???");
67 /*      if ((ptr = luaL_checkudata(L,i,TASK_MODULE_NAME))) {
68         p+=sprintf(p,"task");
69       } else {
70         p+=printf(p,"%s", lua_typename(L, t));
71       }*/
72       break;
73
74     }
75     p += sprintf(p, "  ");      /* put a separator */
76   }
77   XBT_INFO("%s%s", msg, buff);
78 }
79
80 /**
81  * @brief Ensures that a userdata on the stack is a task
82  * and returns the pointer inside the userdata.
83  * @param L a Lua state
84  * @param index an index in the Lua stack
85  * @return the task at this index
86  */
87 static m_task_t checkTask(lua_State * L, int index)
88 {
89   m_task_t *pi, tk;
90   luaL_checktype(L, index, LUA_TTABLE);
91   lua_getfield(L, index, "__simgrid_task");
92   pi = (m_task_t *) luaL_checkudata(L, -1, TASK_MODULE_NAME);
93   if (pi == NULL)
94     luaL_typerror(L, index, TASK_MODULE_NAME);
95   tk = *pi;
96   if (!tk)
97     luaL_error(L, "null Task");
98   lua_pop(L, 1);
99   return tk;
100 }
101
102 /* ********************************************************************************* */
103 /*                           wrapper functions                                       */
104 /* ********************************************************************************* */
105
106 /**
107  * A task is either something to compute somewhere, or something to exchange between two hosts (or both).
108  * It is defined by a computing amount and a message size.
109  *
110  */
111
112 /* *              * *
113  * * Constructors * *
114  * *              * */
115
116 /**
117  * @brief Constructs a new task with the specified processing amount and amount
118  * of data needed.
119  *
120  * @param name  Task's name
121  *
122  * @param computeDuration       A value of the processing amount (in flop) needed to process the task.
123  *                              If 0, then it cannot be executed with the execute() method.
124  *                              This value has to be >= 0.
125  *
126  * @param messageSize           A value of amount of data (in bytes) needed to transfert this task.
127  *                              If 0, then it cannot be transfered with the get() and put() methods.
128  *                              This value has to be >= 0.
129  */
130 static int Task_new(lua_State * L)
131 {
132   XBT_DEBUG("Task new...");
133   const char *name = luaL_checkstring(L, 1);
134   int comp_size = luaL_checkint(L, 2);
135   int msg_size = luaL_checkint(L, 3);
136   m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
137   lua_newtable(L);              /* create a table, put the userdata on top of it */
138   m_task_t *lua_task = (m_task_t *) lua_newuserdata(L, sizeof(m_task_t));
139   *lua_task = msg_task;
140   luaL_getmetatable(L, TASK_MODULE_NAME);
141   lua_setmetatable(L, -2);
142   lua_setfield(L, -2, "__simgrid_task");        /* put the userdata as field of the table */
143   /* remove the args from the stack */
144   lua_remove(L, 1);
145   lua_remove(L, 1);
146   lua_remove(L, 1);
147   return 1;
148 }
149
150 static int Task_get_name(lua_State * L)
151 {
152   m_task_t tk = checkTask(L, -1);
153   lua_pushstring(L, MSG_task_get_name(tk));
154   return 1;
155 }
156
157 static int Task_computation_duration(lua_State * L)
158 {
159   m_task_t tk = checkTask(L, -1);
160   lua_pushnumber(L, MSG_task_get_compute_duration(tk));
161   return 1;
162 }
163
164 static int Task_execute(lua_State * L)
165 {
166   m_task_t tk = checkTask(L, -1);
167   int res = MSG_task_execute(tk);
168   lua_pushnumber(L, res);
169   return 1;
170 }
171
172 static int Task_destroy(lua_State * L)
173 {
174   m_task_t tk = checkTask(L, -1);
175   int res = MSG_task_destroy(tk);
176   lua_pushnumber(L, res);
177   return 1;
178 }
179
180 static int Task_send(lua_State * L)
181 {
182   //stackDump("send ",L);
183   m_task_t tk = checkTask(L, 1);
184   const char *mailbox = luaL_checkstring(L, 2);
185   lua_pop(L, 1);                // remove the string so that the task is on top of it
186   MSG_task_set_data(tk, L);     // Copy my stack into the task, so that the receiver can copy the lua task directly
187   MSG_error_t res = MSG_task_send(tk, mailbox);
188   while (MSG_task_get_data(tk) != NULL) // Don't mess up with my stack: the receiver didn't copy the data yet
189     MSG_process_sleep(0);       // yield
190
191   if (res != MSG_OK)
192     switch (res) {
193     case MSG_TIMEOUT:
194       XBT_DEBUG("MSG_task_send failed : Timeout");
195       break;
196     case MSG_TRANSFER_FAILURE:
197       XBT_DEBUG("MSG_task_send failed : Transfer Failure");
198       break;
199     case MSG_HOST_FAILURE:
200       XBT_DEBUG("MSG_task_send failed : Host Failure ");
201       break;
202     default:
203       XBT_ERROR
204           ("MSG_task_send failed : Unexpected error , please report this bug");
205       break;
206     }
207   return 0;
208 }
209
210 static int Task_recv_with_timeout(lua_State *L)
211 {
212   m_task_t tk = NULL;
213   const char *mailbox = luaL_checkstring(L, -2);
214   int timeout = luaL_checknumber(L, -1);
215   MSG_error_t res = MSG_task_receive_with_timeout(&tk, mailbox, timeout);
216
217   if (res == MSG_OK) {
218     lua_State *sender_stack = MSG_task_get_data(tk);
219     lua_xmove(sender_stack, L, 1);        // copy the data directly from sender's stack
220     MSG_task_set_data(tk, NULL);
221   }
222   else {
223     switch (res) {
224     case MSG_TIMEOUT:
225       XBT_DEBUG("MSG_task_receive failed : Timeout");
226       break;
227     case MSG_TRANSFER_FAILURE:
228       XBT_DEBUG("MSG_task_receive failed : Transfer Failure");
229       break;
230     case MSG_HOST_FAILURE:
231       XBT_DEBUG("MSG_task_receive failed : Host Failure ");
232       break;
233     default:
234       XBT_ERROR("MSG_task_receive failed : Unexpected error , please report this bug");
235       break;
236     }
237     lua_pushnil(L);
238   }
239   return 1;
240 }
241
242 static int Task_recv(lua_State * L)
243 {
244   lua_pushnumber(L, -1.0);
245   return Task_recv_with_timeout(L);
246 }
247
248 static const luaL_reg Task_methods[] = {
249   {"new", Task_new},
250   {"name", Task_get_name},
251   {"computation_duration", Task_computation_duration},
252   {"execute", Task_execute},
253   {"destroy", Task_destroy},
254   {"send", Task_send},
255   {"recv", Task_recv},
256   {"recv_timeout", Task_recv_with_timeout},
257   {NULL, NULL}
258 };
259
260 static int Task_gc(lua_State * L)
261 {
262   m_task_t tk = checkTask(L, -1);
263   if (tk)
264     MSG_task_destroy(tk);
265   return 0;
266 }
267
268 static int Task_tostring(lua_State * L)
269 {
270   lua_pushfstring(L, "Task :%p", lua_touserdata(L, 1));
271   return 1;
272 }
273
274 static const luaL_reg Task_meta[] = {
275   {"__gc", Task_gc},
276   {"__tostring", Task_tostring},
277   {NULL, NULL}
278 };
279
280 /**
281  * Host
282  */
283 static m_host_t checkHost(lua_State * L, int index)
284 {
285   m_host_t *pi, ht;
286   luaL_checktype(L, index, LUA_TTABLE);
287   lua_getfield(L, index, "__simgrid_host");
288   pi = (m_host_t *) luaL_checkudata(L, -1, HOST_MODULE_NAME);
289   if (pi == NULL)
290     luaL_typerror(L, index, HOST_MODULE_NAME);
291   ht = *pi;
292   if (!ht)
293     luaL_error(L, "null Host");
294   lua_pop(L, 1);
295   return ht;
296 }
297
298 static int Host_get_by_name(lua_State * L)
299 {
300   const char *name = luaL_checkstring(L, 1);
301   XBT_DEBUG("Getting Host from name...");
302   m_host_t msg_host = MSG_get_host_by_name(name);
303   if (!msg_host) {
304     luaL_error(L, "null Host : MSG_get_host_by_name failed");
305   }
306   lua_newtable(L);              /* create a table, put the userdata on top of it */
307   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
308   *lua_host = msg_host;
309   luaL_getmetatable(L, HOST_MODULE_NAME);
310   lua_setmetatable(L, -2);
311   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
312   /* remove the args from the stack */
313   lua_remove(L, 1);
314   return 1;
315 }
316
317 static int Host_get_name(lua_State * L)
318 {
319   m_host_t ht = checkHost(L, -1);
320   lua_pushstring(L, MSG_host_get_name(ht));
321   return 1;
322 }
323
324 static int Host_number(lua_State * L)
325 {
326   lua_pushnumber(L, MSG_get_host_number());
327   return 1;
328 }
329
330 static int Host_at(lua_State * L)
331 {
332   int index = luaL_checkinteger(L, 1);
333   m_host_t host = MSG_get_host_table()[index - 1];      // lua indexing start by 1 (lua[1] <=> C[0])
334   lua_newtable(L);              /* create a table, put the userdata on top of it */
335   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
336   *lua_host = host;
337   luaL_getmetatable(L, HOST_MODULE_NAME);
338   lua_setmetatable(L, -2);
339   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
340   return 1;
341
342 }
343
344 static int Host_self(lua_State * L)
345 {
346   m_host_t host = MSG_host_self();
347   lua_newtable(L);
348   m_host_t *lua_host =(m_host_t *)lua_newuserdata(L,sizeof(m_host_t));
349   *lua_host = host;
350   luaL_getmetatable(L, HOST_MODULE_NAME);
351   lua_setmetatable(L, -2);
352   lua_setfield(L, -2, "__simgrid_host");
353   return 1;
354 }
355
356 static int Host_get_property_value(lua_State * L)
357 {
358   m_host_t ht = checkHost(L, -2);
359   const char *prop = luaL_checkstring(L, -1);
360   lua_pushstring(L,MSG_host_get_property_value(ht,prop));
361   return 1;
362 }
363
364 static int Host_sleep(lua_State *L)
365 {
366   int time = luaL_checknumber(L, -1);
367   MSG_process_sleep(time);
368   return 1;
369 }
370
371 static int Host_destroy(lua_State *L)
372 {
373   m_host_t ht = checkHost(L, -1);
374   __MSG_host_destroy(ht);
375   return 1;
376 }
377
378 /* ********************************************************************************* */
379 /*                           lua_stub_generator functions                            */
380 /* ********************************************************************************* */
381
382 xbt_dict_t process_function_set;
383 xbt_dynar_t process_list;
384 xbt_dict_t machine_set;
385 static s_process_t process;
386
387 void s_process_free(void *process)
388 {
389   s_process_t *p = (s_process_t *) process;
390   int i;
391   for (i = 0; i < p->argc; i++)
392     free(p->argv[i]);
393   free(p->argv);
394   free(p->host);
395 }
396
397 static int gras_add_process_function(lua_State * L)
398 {
399   const char *arg;
400   const char *process_host = luaL_checkstring(L, 1);
401   const char *process_function = luaL_checkstring(L, 2);
402
403   if (xbt_dict_is_empty(machine_set)
404       || xbt_dict_is_empty(process_function_set)
405       || xbt_dynar_is_empty(process_list)) {
406     process_function_set = xbt_dict_new();
407     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
408     machine_set = xbt_dict_new();
409   }
410
411   xbt_dict_set(machine_set, process_host, NULL, NULL);
412   xbt_dict_set(process_function_set, process_function, NULL, NULL);
413
414   process.argc = 1;
415   process.argv = xbt_new(char *, 1);
416   process.argv[0] = xbt_strdup(process_function);
417   process.host = strdup(process_host);
418
419   lua_pushnil(L);
420   while (lua_next(L, 3) != 0) {
421     arg = lua_tostring(L, -1);
422     process.argc++;
423     process.argv =
424         xbt_realloc(process.argv, (process.argc) * sizeof(char *));
425     process.argv[(process.argc) - 1] = xbt_strdup(arg);
426
427     XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
428            lua_tostring(L, -1));
429     lua_pop(L, 1);
430   }
431   lua_pop(L, 1);
432   //add to the process list
433   xbt_dynar_push(process_list, &process);
434   return 0;
435 }
436
437
438 static int gras_generate(lua_State * L)
439 {
440   const char *project_name = luaL_checkstring(L, 1);
441   generate_sim(project_name);
442   generate_rl(project_name);
443   generate_makefile_local(project_name);
444   return 0;
445 }
446
447 /***********************************
448  *      Tracing
449  **********************************/
450 static int trace_start(lua_State *L)
451 {
452 #ifdef HAVE_TRACING
453   TRACE_start();
454 #endif
455   return 1;
456 }
457
458 static int trace_category(lua_State * L)
459 {
460 #ifdef HAVE_TRACING
461   TRACE_category(luaL_checkstring(L, 1));
462 #endif
463   return 1;
464 }
465
466 static int trace_set_task_category(lua_State *L)
467 {
468 #ifdef HAVE_TRACING
469   TRACE_msg_set_task_category(checkTask(L, -2), luaL_checkstring(L, -1));
470 #endif
471   return 1;
472 }
473
474 static int trace_end(lua_State *L)
475 {
476 #ifdef HAVE_TRACING
477   TRACE_end();
478 #endif
479   return 1;
480 }
481
482 // *********** Register Methods ******************************************* //
483
484 /*
485  * Host Methods
486  */
487 static const luaL_reg Host_methods[] = {
488   {"getByName", Host_get_by_name},
489   {"name", Host_get_name},
490   {"number", Host_number},
491   {"at", Host_at},
492   {"self", Host_self},
493   {"getPropValue", Host_get_property_value},
494   {"sleep", Host_sleep},
495   {"destroy", Host_destroy},
496   // Bypass XML Methods
497   {"setFunction", console_set_function},
498   {"setProperty", console_host_set_property},
499   {NULL, NULL}
500 };
501
502 static int Host_gc(lua_State * L)
503 {
504   m_host_t ht = checkHost(L, -1);
505   if (ht)
506     ht = NULL;
507   return 0;
508 }
509
510 static int Host_tostring(lua_State * L)
511 {
512   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
513   return 1;
514 }
515
516 static const luaL_reg Host_meta[] = {
517   {"__gc", Host_gc},
518   {"__tostring", Host_tostring},
519   {0, 0}
520 };
521
522 /*
523  * AS Methods
524  */
525 static const luaL_reg AS_methods[] = {
526   {"new", console_add_AS},
527   {"addHost", console_add_host},
528   {"addLink", console_add_link},
529   {"addRoute", console_add_route},
530   {NULL, NULL}
531 };
532
533 /**
534  * Tracing Functions
535  */
536 static const luaL_reg Trace_methods[] = {
537   {"start", trace_start},
538   {"category", trace_category},
539   {"setTaskCategory", trace_set_task_category},
540   {"finish", trace_end},
541   {NULL, NULL}
542 };
543
544 /*
545  * Environment related
546  */
547
548 /**
549  * @brief Runs a Lua function as a new simulated process.
550  * @param argc number of arguments of the function
551  * @param argv name of the Lua function and array of its arguments
552  * @return result of the function
553  */
554 static int run_lua_code(int argc, char **argv)
555 {
556   XBT_DEBUG("Run lua code %s", argv[0]);
557
558   lua_State *L = lua_newthread(lua_maestro_state);
559   int ref = luaL_ref(lua_maestro_state, LUA_REGISTRYINDEX);     /* protect the thread from being garbage collected */
560   int res = 1;
561
562   /* start the co-routine */
563   lua_getglobal(L, argv[0]);
564   xbt_assert(lua_isfunction(L, -1),
565               "The lua function %s does not seem to exist", argv[0]);
566
567   /* push arguments onto the stack */
568   int i;
569   for (i = 1; i < argc; i++)
570     lua_pushstring(L, argv[i]);
571
572   /* call the function */
573   int err;
574   err = lua_pcall(L, argc - 1, 1, 0);
575   xbt_assert(err == 0, "error running function `%s': %s", argv[0],
576               lua_tostring(L, -1));
577
578   /* retrieve result */
579   if (lua_isnumber(L, -1)) {
580     res = lua_tonumber(L, -1);
581     lua_pop(L, 1);              /* pop returned value */
582   }
583
584   /* cleanups */
585   luaL_unref(lua_maestro_state, LUA_REGISTRYINDEX, ref);
586   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
587
588   return res;
589 }
590
591 static int launch_application(lua_State * L)
592 {
593   const char *file = luaL_checkstring(L, 1);
594   MSG_function_register_default(run_lua_code);
595   MSG_launch_application(file);
596   return 0;
597 }
598
599 static int create_environment(lua_State * L)
600 {
601   const char *file = luaL_checkstring(L, 1);
602   XBT_DEBUG("Loading environment file %s", file);
603   MSG_create_environment(file);
604   return 0;
605 }
606
607 static int debug(lua_State * L)
608 {
609   const char *str = luaL_checkstring(L, 1);
610   XBT_DEBUG("%s", str);
611   return 0;
612 }
613
614 static int info(lua_State * L)
615 {
616   const char *str = luaL_checkstring(L, 1);
617   XBT_INFO("%s", str);
618   return 0;
619 }
620
621 static int run(lua_State * L)
622 {
623   MSG_main();
624   return 0;
625 }
626
627 static int clean(lua_State * L)
628 {
629   MSG_clean();
630   return 0;
631 }
632
633 /*
634  * Bypass XML Parser (lua console)
635  */
636
637 /*
638  * Register platform for MSG
639  */
640 static int msg_register_platform(lua_State * L)
641 {
642   /* Tell Simgrid we dont wanna use its parser */
643   surf_parse = console_parse_platform;
644   surf_parse_reset_callbacks();
645   surf_config_models_setup(NULL);
646   MSG_create_environment(NULL);
647   return 0;
648 }
649
650 /*
651  * Register platform for Simdag
652  */
653
654 static int sd_register_platform(lua_State * L)
655 {
656   surf_parse = console_parse_platform_wsL07;
657   surf_parse_reset_callbacks();
658   surf_config_models_setup(NULL);
659   SD_create_environment(NULL);
660   return 0;
661 }
662
663 /*
664  * Register platform for gras
665  */
666 static int gras_register_platform(lua_State * L)
667 {
668   /* Tell Simgrid we dont wanna use surf parser */
669   surf_parse = console_parse_platform;
670   surf_parse_reset_callbacks();
671   surf_config_models_setup(NULL);
672   gras_create_environment(NULL);
673   return 0;
674 }
675
676 /**
677  * Register applicaiton for MSG
678  */
679 static int msg_register_application(lua_State * L)
680 {
681   MSG_function_register_default(run_lua_code);
682   surf_parse = console_parse_application;
683   MSG_launch_application(NULL);
684   return 0;
685 }
686
687 /*
688  * Register application for gras
689  */
690 static int gras_register_application(lua_State * L)
691 {
692   gras_function_register_default(run_lua_code);
693   surf_parse = console_parse_application;
694   gras_launch_application(NULL);
695   return 0;
696 }
697
698 static const luaL_Reg simgrid_funcs[] = {
699   {"create_environment", create_environment},
700   {"launch_application", launch_application},
701   {"debug", debug},
702   {"info", info},
703   {"run", run},
704   {"clean", clean},
705   /* short names */
706   {"platform", create_environment},
707   {"application", launch_application},
708   /* methods to bypass XML parser */
709   {"msg_register_platform", msg_register_platform},
710   {"sd_register_platform", sd_register_platform},
711   {"msg_register_application", msg_register_application},
712   {"gras_register_platform", gras_register_platform},
713   {"gras_register_application", gras_register_application},
714   /* gras sub generator method */
715   {"gras_set_process_function", gras_add_process_function},
716   {"gras_generate", gras_generate},
717   {NULL, NULL}
718 };
719
720 /* ********************************************************************************* */
721 /*                       module management functions                                 */
722 /* ********************************************************************************* */
723
724 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
725
726 int luaopen_simgrid(lua_State *L);     // Fuck gcc: we don't need that prototype
727
728 /**
729  * This function is called automatically by the Lua interpreter when some Lua code requires
730  * the "simgrid" module.
731  * @param L the Lua state
732  */
733 int luaopen_simgrid(lua_State *L)
734 {
735   XBT_DEBUG("luaopen_simgrid *****");
736
737   /* Get the command line arguments from the lua interpreter */
738   char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
739   int argc = 1;
740   argv[0] = (char *) "/usr/bin/lua";    /* Lie on the argv[0] so that the stack dumping facilities find the right binary. FIXME: what if lua is not in that location? */
741
742   lua_getglobal(L, "arg");
743   /* if arg is a null value, it means we use lua only as a script to init platform
744    * else it should be a table and then take arg in consideration
745    */
746   if (lua_istable(L, -1)) {
747     int done = 0;
748     while (!done) {
749       argc++;
750       lua_pushinteger(L, argc - 2);
751       lua_gettable(L, -2);
752       if (lua_isnil(L, -1)) {
753         done = 1;
754       } else {
755         xbt_assert(lua_isstring(L, -1),
756                     "argv[%d] got from lua is no string", argc - 1);
757         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
758                     "Too many arguments, please increase LUA_MAX_ARGS_COUNT in %s before recompiling SimGrid if you insist on having more than %d args on command line",
759                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
760         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
761         lua_pop(L, 1);
762         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
763       }
764     }
765     argv[argc--] = NULL;
766
767     /* Initialize the MSG core */
768     MSG_global_init(&argc, argv);
769     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
770   }
771
772   /* Keep the context mechanism informed of our lua world today */
773   lua_maestro_state = L;
774
775   register_c_functions(L);
776
777   return 1;
778 }
779
780 /**
781  * Makes the appropriate Simgrid functions available to the Lua world.
782  * @param L a Lua world
783  */
784 void register_c_functions(lua_State *L) {
785
786   /* register the core C functions to lua */
787   luaL_register(L, "simgrid", simgrid_funcs);
788
789   /* register the task methods to lua */
790   luaL_openlib(L, TASK_MODULE_NAME, Task_methods, 0);   // create methods table, add it to the globals
791   luaL_newmetatable(L, TASK_MODULE_NAME);       // create metatable for Task, add it to the Lua registry
792   luaL_openlib(L, 0, Task_meta, 0);     // fill metatable
793   lua_pushliteral(L, "__index");
794   lua_pushvalue(L, -3);         // dup methods table
795   lua_rawset(L, -3);            // matatable.__index = methods
796   lua_pushliteral(L, "__metatable");
797   lua_pushvalue(L, -3);         // dup methods table
798   lua_rawset(L, -3);            // hide metatable:metatable.__metatable = methods
799   lua_pop(L, 1);                // drop metatable
800
801   /* register the hosts methods to lua */
802   luaL_openlib(L, HOST_MODULE_NAME, Host_methods, 0);
803   luaL_newmetatable(L, HOST_MODULE_NAME);
804   luaL_openlib(L, 0, Host_meta, 0);
805   lua_pushliteral(L, "__index");
806   lua_pushvalue(L, -3);
807   lua_rawset(L, -3);
808   lua_pushliteral(L, "__metatable");
809   lua_pushvalue(L, -3);
810   lua_rawset(L, -3);
811   lua_pop(L, 1);
812
813   /* register the links methods to lua */
814   luaL_openlib(L, AS_MODULE_NAME, AS_methods, 0);
815   luaL_newmetatable(L, AS_MODULE_NAME);
816   lua_pop(L, 1);
817
818   /* register the Tracing functions to lua */
819   luaL_openlib(L, TRACE_MODULE_NAME, Trace_methods, 0);
820   luaL_newmetatable(L, TRACE_MODULE_NAME);
821   lua_pop(L, 1);
822 }