Logo AND Algorithmique Numérique Distribuée

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