Logo AND Algorithmique Numérique Distribuée

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