Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
349658822851fea7b28ee7fee5e2f004a6748586
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* Copyright (c) 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* SimGrid Lua bindings                                                     */
8
9 #include "simgrid_lua.h"
10 #include "lua_state_cloner.h"
11 #include "lua_utils.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
14
15 #define TASK_MODULE_NAME "simgrid.task"
16 #define HOST_MODULE_NAME "simgrid.host"
17 // Surf (bypass XML)
18 #define LINK_MODULE_NAME "simgrid.link"
19 #define ROUTE_MODULE_NAME "simgrid.route"
20 #define PLATF_MODULE_NAME "simgrid.platf"
21
22 static lua_State* sglua_maestro_state;
23
24 int luaopen_simgrid(lua_State *L);
25 static void register_c_functions(lua_State *L);
26 static int run_lua_code(int argc, char **argv);
27
28 /* ********************************************************************************* */
29 /*                                simgrid.task API                                   */
30 /* ********************************************************************************* */
31
32 /**
33  * \brief Ensures that a value in the stack is a valid task and returns it.
34  * \param L a Lua state
35  * \param index an index in the Lua stack
36  * \return the C task corresponding to this Lua task
37  */
38 static m_task_t sglua_checktask(lua_State* L, int index)
39 {
40   sglua_stack_dump("check task: ", L);
41   luaL_checktype(L, index, LUA_TTABLE);
42                                   /* ... task ... */
43   lua_getfield(L, index, "__simgrid_task");
44                                   /* ... task ... ctask */
45   m_task_t task = *((m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME));
46   lua_pop(L, 1);
47                                   /* ... task ... */
48
49   if (task == NULL) {
50     luaL_error(L, "This task was sent to someone else, you cannot access it anymore");
51   }
52
53   return task;
54 }
55
56 /**
57  * \brief Creates a new task and leaves it onto the stack.
58  * \param L a Lua state
59  * \return number of values returned to Lua
60  *
61  * - Argument 1 (string): name of the task
62  * - Argument 2 (number): computation size
63  * - Argument 3 (number): communication size
64  * - Return value (task): the task created
65  */
66 static int l_task_new(lua_State* L)
67 {
68   XBT_DEBUG("Task new");
69   const char* name = luaL_checkstring(L, 1);
70   int comp_size = luaL_checkint(L, 2);
71   int msg_size = luaL_checkint(L, 3);
72                                   /* name comp comm */
73   lua_settop(L, 0);
74                                   /* -- */
75   m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
76
77   lua_newtable(L);
78                                   /* task */
79   m_task_t* lua_task = (m_task_t*) lua_newuserdata(L, sizeof(m_task_t));
80                                   /* task ctask */
81   *lua_task = msg_task;
82   luaL_getmetatable(L, TASK_MODULE_NAME);
83                                   /* task ctask mt */
84   lua_setmetatable(L, -2);
85                                   /* task ctask */
86   lua_setfield(L, -2, "__simgrid_task");
87                                   /* task */
88   return 1;
89 }
90
91 /**
92  * \brief Returns the name of a task.
93  * \param L a Lua state
94  * \return number of values returned to Lua
95  *
96  * - Argument 1 (task): a task
97  * - Return value (string): name of the task
98  */
99 static int l_task_get_name(lua_State* L)
100 {
101   m_task_t task = sglua_checktask(L, 1);
102   lua_pushstring(L, MSG_task_get_name(task));
103   return 1;
104 }
105
106 /**
107  * \brief Returns the computation duration of a task.
108  * \param L a Lua state
109  * \return number of values returned to Lua
110  *
111  * - Argument 1 (task): a task
112  * - Return value (number): computation duration of this task
113  */
114 static int l_task_computation_duration(lua_State* L)
115 {
116   m_task_t task = sglua_checktask(L, 1);
117   lua_pushnumber(L, MSG_task_get_compute_duration(task));
118   return 1;
119 }
120
121 /**
122  * \brief Executes a task.
123  * \param L a Lua state
124  * \return number of values returned to Lua
125  *
126  * - Argument 1 (task): the task to execute
127  * - Return value (number): error code
128  */
129 static int l_task_execute(lua_State* L)
130 {
131   m_task_t task = sglua_checktask(L, 1);
132   int res = MSG_task_execute(task);
133   lua_pushnumber(L, res);
134   return 1;
135 }
136
137 /**
138  * \brief Sends a task to a mailbox and waits for its completion.
139  * \param L a Lua state
140  * \return number of values returned to Lua
141  *
142  * - Argument 1 (task): the task to send
143  * - Argument 2 (string): mailbox
144  */
145 static int l_task_send(lua_State* L)
146 {
147   m_task_t task = sglua_checktask(L, 1);
148   const char* mailbox = luaL_checkstring(L, 2);
149                                   /* task mailbox */
150   lua_settop(L, 1);
151                                   /* task */
152   /* copy my stack into the task, so that the receiver can copy the lua task */
153   MSG_task_set_data(task, L);
154   MSG_error_t res = MSG_task_send(task, mailbox);
155   while (MSG_task_get_data(task) != NULL) {
156     /* don't mess up with my stack: the receiver didn't copy the data yet */
157     MSG_process_sleep(0);
158   }
159
160   if (res == MSG_OK) {
161     /* the receiver is the owner of the task and may destroy it:
162      * remove the C task on my side so that I don't garbage collect it */
163     lua_getfield(L, 1, "__simgrid_task");
164                                   /* task ctask */
165     m_task_t* udata = (m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME);
166     *udata = NULL;
167     lua_pop(L, 1);
168                                   /* task */
169   }
170   else {
171     switch (res) {
172     case MSG_TIMEOUT:
173       XBT_DEBUG("MSG_task_send failed : Timeout");
174       break;
175     case MSG_TRANSFER_FAILURE:
176       XBT_DEBUG("MSG_task_send failed : Transfer Failure");
177       break;
178     case MSG_HOST_FAILURE:
179       XBT_DEBUG("MSG_task_send failed : Host Failure ");
180       break;
181     default:
182       XBT_ERROR
183           ("MSG_task_send failed : Unexpected error , please report this bug");
184       break;
185     }
186   }
187   return 0;
188 }
189
190 /**
191  * \brief Receives a task.
192  * \param L a Lua state
193  * \return number of values returned to Lua
194  *
195  * - Argument 1 (string): mailbox
196  * - Argument 2 (number, optional): timeout (default is no timeout)
197  * - Return value (task/nil): the task received or nil if the communication
198  * has failed
199  */
200 static int l_task_recv(lua_State *L)
201 {
202   m_task_t task = NULL;
203   const char* mailbox = luaL_checkstring(L, 1);
204   int timeout;
205   if (lua_gettop(L) >= 2) {
206                                   /* mailbox timeout */
207     timeout = luaL_checknumber(L, 2);
208   }
209   else {
210                                   /* mailbox */
211     timeout = -1;
212     /* no timeout by default */
213   }
214   lua_settop(L, 0);
215                                   /* -- */
216   MSG_error_t res = MSG_task_receive_with_timeout(&task, mailbox, timeout);
217
218   if (res == MSG_OK) {
219     /* copy the data directly from sender's stack */
220     lua_State* sender_stack = MSG_task_get_data(task);
221     sglua_copy_value(sender_stack, L);
222                                   /* task */
223     MSG_task_set_data(task, NULL);
224   }
225   else {
226     switch (res) {
227     case MSG_TIMEOUT:
228       XBT_DEBUG("MSG_task_receive failed : Timeout");
229       break;
230     case MSG_TRANSFER_FAILURE:
231       XBT_DEBUG("MSG_task_receive failed : Transfer Failure");
232       break;
233     case MSG_HOST_FAILURE:
234       XBT_DEBUG("MSG_task_receive failed : Host Failure ");
235       break;
236     default:
237       XBT_ERROR("MSG_task_receive failed : Unexpected error , please report this bug");
238       break;
239     }
240     lua_pushnil(L);
241                                   /* nil */
242   }
243                                   /* task/nil */
244   return 1;
245 }
246
247 static const luaL_reg task_functions[] = {
248   {"new", l_task_new},
249   {"name", l_task_get_name},
250   {"computation_duration", l_task_computation_duration},
251   {"execute", l_task_execute},
252   {"send", l_task_send},
253   {"recv", l_task_recv},
254   {NULL, NULL}
255 };
256
257 /**
258  * \brief Finalizes the userdata of a task.
259  * \param L a Lua state
260  * \return number of values returned to Lua
261  *
262  * - Argument 1 (userdata): a C task, possibly NULL if it was sent to another
263  * Lua state
264  */
265 static int l_task_gc(lua_State* L)
266 {
267                                   /* ctask */
268   m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
269   /* the task is NULL if I sent it to someone else */
270   if (task != NULL) {
271     MSG_task_destroy(task);
272   }
273   return 0;
274 }
275
276 /**
277  * \brief Returns a string representation of a C task.
278  * \param L a Lua state
279  * \return number of values returned to Lua
280  *
281  * - Argument 1 (userdata): a task
282  * - Return value (string): a string describing this task
283  */
284 static int l_task_tostring(lua_State* L)
285 {
286   m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
287   lua_pushfstring(L, "Task: %p", task);
288   return 1;
289 }
290
291 static const luaL_reg task_meta[] = {
292   {"__gc", l_task_gc},
293   {"__tostring", l_task_tostring},
294   {NULL, NULL}
295 };
296
297 /* ********************************************************************************* */
298 /*                                simgrid.host API                                   */
299 /* ********************************************************************************* */
300
301 /**
302  * \brief Ensures that a value in the stack is a host and returns it.
303  * \param L a Lua state
304  * \param index an index in the Lua stack
305  * \return the C host corresponding to this Lua host
306  */
307 static m_host_t sglua_checkhost(lua_State * L, int index)
308 {
309   m_host_t *pi, ht;
310   luaL_checktype(L, index, LUA_TTABLE);
311   lua_getfield(L, index, "__simgrid_host");
312   pi = (m_host_t *) luaL_checkudata(L, lua_gettop(L), HOST_MODULE_NAME);
313   if (pi == NULL)
314     luaL_typerror(L, index, HOST_MODULE_NAME);
315   ht = *pi;
316   if (!ht)
317     luaL_error(L, "null Host");
318   lua_pop(L, 1);
319   return ht;
320 }
321
322 /**
323  * \brief Returns a host given its name.
324  * \param L a Lua state
325  * \return number of values returned to Lua
326  *
327  * - Argument 1 (string): name of a host
328  * - Return value (host): the corresponding host
329  */
330 static int l_host_get_by_name(lua_State * L)
331 {
332   const char *name = luaL_checkstring(L, 1);
333   XBT_DEBUG("Getting Host from name...");
334   m_host_t msg_host = MSG_get_host_by_name(name);
335   if (!msg_host) {
336     luaL_error(L, "null Host : MSG_get_host_by_name failed");
337   }
338   lua_newtable(L);              /* create a table, put the userdata on top of it */
339   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
340   *lua_host = msg_host;
341   luaL_getmetatable(L, HOST_MODULE_NAME);
342   lua_setmetatable(L, -2);
343   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
344   /* remove the args from the stack */
345   lua_remove(L, 1);
346   return 1;
347 }
348
349 /**
350  * \brief Returns the name of a host.
351  * \param L a Lua state
352  * \return number of values returned to Lua
353  *
354  * - Argument 1 (host): a host
355  * - Return value (string): name of this host
356  */
357 static int l_host_get_name(lua_State * L)
358 {
359   m_host_t ht = sglua_checkhost(L, 1);
360   lua_pushstring(L, MSG_host_get_name(ht));
361   return 1;
362 }
363
364 /**
365  * \brief Returns the number of existing hosts.
366  * \param L a Lua state
367  * \return number of values returned to Lua
368  *
369  * - Return value (number): number of hosts
370  */
371 static int l_host_number(lua_State * L)
372 {
373   lua_pushnumber(L, MSG_get_host_number());
374   return 1;
375 }
376
377 /**
378  * \brief Returns the host given its index.
379  * \param L a Lua state
380  * \return number of values returned to Lua
381  *
382  * - Argument 1 (number): an index (1 is the first)
383  * - Return value (host): the host at this index
384  */
385 static int l_host_at(lua_State * L)
386 {
387   int index = luaL_checkinteger(L, 1);
388   m_host_t host = MSG_get_host_table()[index - 1];      // lua indexing start by 1 (lua[1] <=> C[0])
389   lua_newtable(L);              /* create a table, put the userdata on top of it */
390   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
391   *lua_host = host;
392   luaL_getmetatable(L, HOST_MODULE_NAME);
393   lua_setmetatable(L, -2);
394   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
395   return 1;
396 }
397
398 /**
399  * \brief Returns the host where the current process is located.
400  * \param L a Lua state
401  * \return number of values returned to Lua
402  *
403  * - Return value (host): the current host
404  */
405 static int l_host_self(lua_State * L)
406 {
407                                   /* -- */
408   m_host_t host = MSG_host_self();
409   lua_newtable(L);
410                                   /* table */
411   m_host_t* lua_host = (m_host_t*) lua_newuserdata(L, sizeof(m_host_t));
412                                   /* table ud */
413   *lua_host = host;
414   luaL_getmetatable(L, HOST_MODULE_NAME);
415                                   /* table ud mt */
416   lua_setmetatable(L, -2);
417                                   /* table ud */
418   lua_setfield(L, -2, "__simgrid_host");
419                                   /* table */
420   return 1;
421 }
422
423 /**
424  * \brief Returns the value of a host property.
425  * \param L a Lua state
426  * \return number of values returned to Lua
427  *
428  * - Argument 1 (host): a host
429  * - Argument 2 (string): name of the property to get
430  * - Return value (string): the value of this property
431  */
432 static int l_host_get_property_value(lua_State * L)
433 {
434   m_host_t ht = sglua_checkhost(L, 1);
435   const char *prop = luaL_checkstring(L, 2);
436   lua_pushstring(L,MSG_host_get_property_value(ht,prop));
437   return 1;
438 }
439
440 /**
441  * \brief Makes the current process sleep for a while.
442  * \param L a Lua state
443  * \return number of values returned to Lua
444  *
445  * - Argument 1 (number): duration of the sleep
446  */
447 static int l_host_sleep(lua_State *L)
448 {
449   int time = luaL_checknumber(L, 1);
450   MSG_process_sleep(time);
451   return 0;
452 }
453
454 /**
455  * \brief Destroys a host.
456  * \param L a Lua state
457  * \return number of values returned to Lua
458  *
459  * - Argument 1 (host): the host to destroy
460  */
461 static int l_host_destroy(lua_State *L)
462 {
463   m_host_t ht = sglua_checkhost(L, 1);
464   __MSG_host_destroy(ht);
465   return 0;
466 }
467
468 static const luaL_reg host_functions[] = {
469   {"get_by_name", l_host_get_by_name},
470   {"name", l_host_get_name},
471   {"number", l_host_number},
472   {"at", l_host_at},
473   {"self", l_host_self},
474   {"get_prop_value", l_host_get_property_value},
475   {"sleep", l_host_sleep},
476   {"destroy", l_host_destroy},
477   // Bypass XML Methods
478   {"set_function", console_set_function},
479   {"set_property", console_host_set_property},
480   {NULL, NULL}
481 };
482
483 /**
484  * \brief Returns a string representation of a host.
485  * \param L a Lua state
486  * \return number of values returned to Lua
487  *
488  * - Argument 1 (userdata): a host
489  * - Return value (string): a string describing this host
490  */
491 static int l_host_tostring(lua_State * L)
492 {
493   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
494   return 1;
495 }
496
497 static const luaL_reg host_meta[] = {
498   {"__tostring", l_host_tostring},
499   {0, 0}
500 };
501
502 /* ********************************************************************************* */
503 /*                           lua_stub_generator functions                            */
504 /* ********************************************************************************* */
505
506 xbt_dict_t process_function_set;
507 xbt_dynar_t process_list;
508 xbt_dict_t machine_set;
509 static s_process_t process;
510
511 void s_process_free(void *process)
512 {
513   s_process_t *p = (s_process_t *) process;
514   int i;
515   for (i = 0; i < p->argc; i++)
516     free(p->argv[i]);
517   free(p->argv);
518   free(p->host);
519 }
520
521 static int gras_add_process_function(lua_State * L)
522 {
523   const char *arg;
524   const char *process_host = luaL_checkstring(L, 1);
525   const char *process_function = luaL_checkstring(L, 2);
526
527   if (xbt_dict_is_empty(machine_set)
528       || xbt_dict_is_empty(process_function_set)
529       || xbt_dynar_is_empty(process_list)) {
530     process_function_set = xbt_dict_new();
531     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
532     machine_set = xbt_dict_new();
533   }
534
535   xbt_dict_set(machine_set, process_host, NULL, NULL);
536   xbt_dict_set(process_function_set, process_function, NULL, NULL);
537
538   process.argc = 1;
539   process.argv = xbt_new(char *, 1);
540   process.argv[0] = xbt_strdup(process_function);
541   process.host = strdup(process_host);
542
543   lua_pushnil(L);
544   while (lua_next(L, 3) != 0) {
545     arg = lua_tostring(L, -1);
546     process.argc++;
547     process.argv =
548         xbt_realloc(process.argv, (process.argc) * sizeof(char *));
549     process.argv[(process.argc) - 1] = xbt_strdup(arg);
550
551     XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
552            lua_tostring(L, -1));
553     lua_pop(L, 1);
554   }
555   lua_pop(L, 1);
556   //add to the process list
557   xbt_dynar_push(process_list, &process);
558   return 0;
559 }
560
561 static int gras_generate(lua_State * L)
562 {
563   const char *project_name = luaL_checkstring(L, 1);
564   generate_sim(project_name);
565   generate_rl(project_name);
566   generate_makefile_local(project_name);
567   return 0;
568 }
569
570 /* ********************************************************************************* */
571 /*                               simgrid.platf API                                   */
572 /* ********************************************************************************* */
573
574 static const luaL_reg platf_functions[] = {
575     {"open", console_open},
576     {"close", console_close},
577     {"AS_open", console_AS_open},
578     {"AS_close", console_AS_close},
579     {"host_new", console_add_host},
580     {"link_new", console_add_link},
581     {"router_new", console_add_router},
582     {"route_new", console_add_route},
583     {NULL, NULL}
584 };
585
586 /* ********************************************************************************* */
587 /*                                  simgrid API                                      */
588 /* ********************************************************************************* */
589
590 /**
591  * \brief Deploys your application.
592  * \param L a Lua state
593  * \return number of values returned to Lua
594  *
595  * - Argument 1 (string): name of the deployment file to load
596  */
597 static int launch_application(lua_State * L)
598 {
599   const char *file = luaL_checkstring(L, 1);
600   MSG_function_register_default(run_lua_code);
601   MSG_launch_application(file);
602   return 0;
603 }
604
605 /**
606  * \brief Creates the platform.
607  * \param L a Lua state
608  * \return number of values returned to Lua
609  *
610  * - Argument 1 (string): name of the platform file to load
611  */
612 static int create_environment(lua_State * L)
613 {
614   const char *file = luaL_checkstring(L, 1);
615   XBT_DEBUG("Loading environment file %s", file);
616   MSG_create_environment(file);
617   return 0;
618 }
619
620 /**
621  * \brief Prints a log string with debug level.
622  * \param L a Lua state
623  * \return number of values returned to Lua
624  *
625  * - Argument 1 (string): the text to print
626  */
627 static int debug(lua_State * L)
628 {
629   const char *str = luaL_checkstring(L, 1);
630   XBT_DEBUG("%s", str);
631   return 0;
632 }
633
634 /**
635  * \brief Prints a log string with info level.
636  * \param L a Lua state
637  * \return number of values returned to Lua
638  *
639  * - Argument 1 (string): the text to print
640  */
641 static int info(lua_State * L)
642 {
643   const char *str = luaL_checkstring(L, 1);
644   XBT_INFO("%s", str);
645   return 0;
646 }
647
648 /**
649  * \brief Runs your application.
650  * \param L a Lua state
651  * \return number of values returned to Lua
652  */
653 static int run(lua_State * L)
654 {
655   MSG_main();
656   return 0;
657 }
658
659 /**
660  * \brief Cleans the simulation.
661  * \param L a Lua state
662  * \return number of values returned to Lua
663  */
664 static int clean(lua_State * L)
665 {
666   MSG_clean();
667   return 0;
668 }
669
670 /*
671  * Register platform for MSG
672  */
673 static int msg_register_platform(lua_State * L)
674 {
675   /* Tell Simgrid we dont wanna use its parser */
676   //surf_parse = console_parse_platform;
677   surf_parse_reset_callbacks();
678   MSG_create_environment(NULL);
679   return 0;
680 }
681
682 /*
683  * Register platform for Simdag
684  */
685
686 static int sd_register_platform(lua_State * L)
687 {
688   //surf_parse = console_parse_platform_wsL07;
689   surf_parse_reset_callbacks();
690   SD_create_environment(NULL);
691   return 0;
692 }
693
694 /*
695  * Register platform for gras
696  */
697 static int gras_register_platform(lua_State * L)
698 {
699   //surf_parse = console_parse_platform;
700   surf_parse_reset_callbacks();
701   gras_create_environment(NULL);
702   return 0;
703 }
704
705 /**
706  * Register applicaiton for MSG
707  */
708 static int msg_register_application(lua_State * L)
709 {
710   MSG_function_register_default(run_lua_code);
711   //surf_parse = console_parse_application;
712   MSG_launch_application(NULL);
713   return 0;
714 }
715
716 /*
717  * Register application for gras
718  */
719 static int gras_register_application(lua_State * L)
720 {
721   gras_function_register_default(run_lua_code);
722   //surf_parse = console_parse_application;
723   gras_launch_application(NULL);
724   return 0;
725 }
726
727 static const luaL_Reg simgrid_functions[] = {
728   {"create_environment", create_environment},
729   {"launch_application", launch_application},
730   {"debug", debug},
731   {"info", info},
732   {"run", run},
733   {"clean", clean},
734   /* short names */
735   {"platform", create_environment},
736   {"application", launch_application},
737   /* methods to bypass XML parser */
738   {"msg_register_platform", msg_register_platform},
739   {"sd_register_platform", sd_register_platform},
740   {"msg_register_application", msg_register_application},
741   {"gras_register_platform", gras_register_platform},
742   {"gras_register_application", gras_register_application},
743   /* gras sub generator method */
744   {"gras_set_process_function", gras_add_process_function},
745   {"gras_generate", gras_generate},
746   {NULL, NULL}
747 };
748
749 /* ********************************************************************************* */
750 /*                           module management functions                             */
751 /* ********************************************************************************* */
752
753 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
754
755 /**
756  * \brief Opens the simgrid Lua module.
757  *
758  * This function is called automatically by the Lua interpreter when some
759  * Lua code requires the "simgrid" module.
760  *
761  * \param L the Lua state
762  */
763 int luaopen_simgrid(lua_State *L)
764 {
765   XBT_DEBUG("luaopen_simgrid *****");
766
767   /* Get the command line arguments from the lua interpreter */
768   char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
769   int argc = 1;
770   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? */
771
772   lua_getglobal(L, "arg");
773   /* if arg is a null value, it means we use lua only as a script to init platform
774    * else it should be a table and then take arg in consideration
775    */
776   if (lua_istable(L, -1)) {
777     int done = 0;
778     while (!done) {
779       argc++;
780       lua_pushinteger(L, argc - 2);
781       lua_gettable(L, -2);
782       if (lua_isnil(L, -1)) {
783         done = 1;
784       } else {
785         xbt_assert(lua_isstring(L, -1),
786                     "argv[%d] got from lua is no string", argc - 1);
787         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
788                     "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",
789                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
790         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
791         lua_pop(L, 1);
792         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
793       }
794     }
795     argv[argc--] = NULL;
796
797     /* Initialize the MSG core */
798     MSG_global_init(&argc, argv);
799     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
800   }
801
802   /* Keep the context mechanism informed of our lua world today */
803   sglua_maestro_state = L;
804
805   /* initialize access to my tables by children Lua states */
806   lua_newtable(L);
807   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
808
809   register_c_functions(L);
810
811   return 1;
812 }
813
814 /**
815  * \brief Returns whether a Lua state is the maestro state.
816  * \param L a Lua state
817  * \return true if this is maestro
818  */
819 int sglua_is_maestro(lua_State* L) {
820   return L == sglua_maestro_state;
821 }
822
823 /**
824  * \brief Returns the maestro state.
825  * \return the maestro Lua state
826  */
827 lua_State* sglua_get_maestro(void) {
828   return sglua_maestro_state;
829 }
830
831 /**
832  * \brief Registers the task functions into the table simgrid.task.
833  *
834  * Also initialize the metatable of the task userdata type.
835  *
836  * \param L a lua state
837  */
838 static void register_task_functions(lua_State* L) {
839
840   /* create a table simgrid.task and fill it with task functions */
841   luaL_openlib(L, TASK_MODULE_NAME, task_functions, 0);
842                                   /* simgrid.task */
843
844   /* create the metatable for tasks, add it to the Lua registry */
845   luaL_newmetatable(L, TASK_MODULE_NAME);
846                                   /* simgrid.task mt */
847   /* fill the metatable */
848   luaL_openlib(L, NULL, task_meta, 0);
849                                   /* simgrid.task mt */
850   lua_pushvalue(L, -2);
851                                   /* simgrid.task mt simgrid.task */
852   /* metatable.__index = simgrid.task
853    * we put the task functions inside the task userdata itself:
854    * this allows to write task:method(args) for
855    * simgrid.task.method(task, args) */
856   // FIXME: in the current implementation, a Lua task is a table with a
857   // __simgrid_task field that contains the userdata, so the OO-style
858   // writing doesn't work
859   lua_setfield(L, -2, "__index");
860                                   /* simgrid.task mt */
861   lua_pop(L, 2);
862                                   /* -- */
863 }
864
865 /**
866  * \brief Registers the host functions into the table simgrid.host.
867  *
868  * Also initialize the metatable of the host userdata type.
869  *
870  * \param L a lua state
871  */
872 static void register_host_functions(lua_State* L) {
873
874   /* create a table simgrid.host and fill it with host functions */
875   luaL_openlib(L, HOST_MODULE_NAME, host_functions, 0);
876                                   /* simgrid.host */
877
878   /* create the metatable for host, add it to the Lua registry */
879   luaL_newmetatable(L, HOST_MODULE_NAME);
880                                   /* simgrid.host mt */
881   /* fill the metatable */
882   luaL_openlib(L, NULL, host_meta, 0);
883                                   /* simgrid.host mt */
884   lua_pushvalue(L, -2);
885                                   /* simgrid.host mt simgrid.host */
886   /* metatable.__index = simgrid.host
887    * we put the host functions inside the host userdata itself:
888    * this allows to write host(args) for
889    * simgrid.host.method(host, args) */
890   // FIXME: cannot work currently, same problem as tasks
891   lua_setfield(L, -2, "__index");
892                                   /* simgrid.host mt */
893   lua_pop(L, 2);
894                                   /* -- */
895 }
896
897 /**
898  * \brief Registers the platform functions into the table simgrid.platf.
899  * \param L a lua state
900  */
901 static void register_platf_functions(lua_State* L) {
902
903   luaL_openlib(L, PLATF_MODULE_NAME, platf_functions, 0);
904                                   /* simgrid.platf */
905   lua_pop(L, 1);
906 }
907
908 /**
909  * \brief Makes the Simgrid functions available to the Lua world.
910  * \param L a Lua world
911  */
912 static void register_c_functions(lua_State *L) {
913
914   /* register the core C functions to lua */
915   luaL_register(L, "simgrid", simgrid_functions);
916                                   /* simgrid */
917   lua_pop(L, 1);
918                                   /* -- */
919   register_task_functions(L);
920   register_host_functions(L);
921   register_platf_functions(L);
922 }
923
924 /**
925  * \brief Runs a Lua function as a new simulated process.
926  * \param argc number of arguments of the function
927  * \param argv name of the Lua function and array of its arguments
928  * \return result of the function
929  */
930 static int run_lua_code(int argc, char **argv)
931 {
932   XBT_DEBUG("Run lua code %s", argv[0]);
933
934   /* create a new state, getting globals from maestro */
935   lua_State *L = sglua_clone_maestro();
936   int res = 1;
937
938   /* start the function */
939   lua_getglobal(L, argv[0]);
940   xbt_assert(lua_isfunction(L, -1),
941               "There is no Lua function with name `%s'", argv[0]);
942
943   /* push arguments onto the stack */
944   int i;
945   for (i = 1; i < argc; i++)
946     lua_pushstring(L, argv[i]);
947
948   /* call the function */
949   _XBT_GNUC_UNUSED int err;
950   err = lua_pcall(L, argc - 1, 1, 0);
951   xbt_assert(err == 0, "Error running function `%s': %s", argv[0],
952               lua_tostring(L, -1));
953
954   /* retrieve result */
955   if (lua_isnumber(L, -1)) {
956     res = lua_tonumber(L, -1);
957     lua_pop(L, 1);              /* pop returned value */
958   }
959
960   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
961
962   return res;
963 }