Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fa6ab955efabfb4da5c12f50ba02fd3abb1b0ae4
[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  * A Lua task is a regular table with a full userdata inside, and both share
67  * the same metatable. For the regular table, the metatable allows OO-style
68  * writing such as your_task:send(someone).
69  * For the userdata, the metatable is used to check its type.
70  */
71 static int l_task_new(lua_State* L)
72 {
73   XBT_DEBUG("Task new");
74   const char* name = luaL_checkstring(L, 1);
75   int comp_size = luaL_checkint(L, 2);
76   int msg_size = luaL_checkint(L, 3);
77                                   /* name comp comm */
78   lua_settop(L, 0);
79                                   /* -- */
80   m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
81
82   lua_newtable(L);
83                                   /* task */
84   luaL_getmetatable(L, TASK_MODULE_NAME);
85                                   /* task mt */
86   lua_setmetatable(L, -2);
87                                   /* task */
88   m_task_t* lua_task = (m_task_t*) lua_newuserdata(L, sizeof(m_task_t));
89                                   /* task ctask */
90   *lua_task = msg_task;
91   luaL_getmetatable(L, TASK_MODULE_NAME);
92                                   /* task ctask mt */
93   lua_setmetatable(L, -2);
94                                   /* task ctask */
95   lua_setfield(L, -2, "__simgrid_task");
96                                   /* task */
97   return 1;
98 }
99
100 /**
101  * \brief Returns the name of a task.
102  * \param L a Lua state
103  * \return number of values returned to Lua
104  *
105  * - Argument 1 (task): a task
106  * - Return value (string): name of the task
107  */
108 static int l_task_get_name(lua_State* L)
109 {
110   m_task_t task = sglua_checktask(L, 1);
111   lua_pushstring(L, MSG_task_get_name(task));
112   return 1;
113 }
114
115 /**
116  * \brief Returns the computation duration of a task.
117  * \param L a Lua state
118  * \return number of values returned to Lua
119  *
120  * - Argument 1 (task): a task
121  * - Return value (number): computation duration of this task
122  */
123 static int l_task_get_computation_duration(lua_State* L)
124 {
125   m_task_t task = sglua_checktask(L, 1);
126   lua_pushnumber(L, MSG_task_get_compute_duration(task));
127   return 1;
128 }
129
130 /**
131  * \brief Executes a task.
132  * \param L a Lua state
133  * \return number of values returned to Lua
134  *
135  * - Argument 1 (task): the task to execute
136  * - Return value (nil or error): none if the task was successfully executed, or an error
137  * string in case of failure, which may be "task canceled" or "host failure"
138  */
139 static int l_task_execute(lua_State* L)
140 {
141   m_task_t task = sglua_checktask(L, 1);
142   MSG_error_t res = MSG_task_execute(task);
143
144   switch (res) {
145
146     case MSG_OK:
147       return 0;
148
149     case MSG_TASK_CANCELED:
150       lua_pushliteral(L, "task canceled");
151       return 1;
152
153     case MSG_HOST_FAILURE:
154       lua_pushliteral(L, "host failure");
155       return 1;
156
157     default:
158       xbt_die("Unexpected result of MSG_task_execute(): %d, please report this bug", res);
159   }
160 }
161
162 /**
163  * \brief Sends a task to a mailbox and waits for its completion.
164  * \param L a Lua state
165  * \return number of values returned to Lua
166  *
167  * - Argument 1 (task): the task to send
168  * - Argument 2 (string or compatible): mailbox name, as a real string or any
169  * type convertible to string (numbers always are)
170  * - Return value (nil or error): none if the communication was successful,
171  * or an error string in case of failure, which may be "timeout",
172  * "host failure" or "transfer failure"
173  */
174 static int l_task_send(lua_State* L)
175 {
176   m_task_t task = sglua_checktask(L, 1);
177   const char* mailbox = luaL_checkstring(L, 2);
178                                   /* task mailbox */
179   lua_settop(L, 1);
180                                   /* task */
181   /* copy my stack into the task, so that the receiver can copy the lua task */
182   MSG_task_set_data(task, L);
183   MSG_error_t res = MSG_task_send(task, mailbox);
184   while (MSG_task_get_data(task) != NULL) {
185     /* don't mess up with my stack: the receiver didn't copy the data yet */
186     MSG_process_sleep(0);
187   }
188
189   switch (res) {
190
191   case MSG_OK:
192     /* the receiver is the owner of the task and may destroy it:
193      * remove the C task on my side so that I don't garbage collect it */
194     lua_getfield(L, 1, "__simgrid_task");
195                                   /* task ctask */
196     m_task_t* udata = (m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME);
197     *udata = NULL;
198     return 0;
199
200   case MSG_TIMEOUT:
201     XBT_DEBUG("MSG_task_send failed: timeout");
202     lua_settop(L, 0);
203     lua_pushliteral(L, "timeout");
204     return 1;
205
206   case MSG_TRANSFER_FAILURE:
207     XBT_DEBUG("MSG_task_send failed: transfer failure");
208     lua_settop(L, 0);
209     lua_pushliteral(L, "transfer failure");
210     return 1;
211
212   case MSG_HOST_FAILURE:
213     XBT_DEBUG("MSG_task_send failed: host failure");
214     lua_settop(L, 0);
215     lua_pushliteral(L, "host failure");
216     return 1;
217
218   default:
219     xbt_die("Unexpected result of MSG_task_send: %d, please report this bug", res);
220   }
221 }
222
223 /**
224  * \brief Receives a task.
225  * \param L a Lua state
226  * \return number of values returned to Lua
227  *
228  * - Argument 1 (string or compatible): mailbox name, as a real string or any
229  * type convertible to string (numbers always are)
230  * - Argument 2 (number, optional): timeout (default is no timeout)
231  * - Return value (task or nil+err): the task received, or nil plus an error message if
232  * the communication 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   switch (res) {
253
254   case MSG_OK:
255     /* copy the data directly from sender's stack */
256   {
257     lua_State* sender_stack = MSG_task_get_data(task);
258     sglua_copy_value(sender_stack, L);
259                                   /* task */
260     MSG_task_set_data(task, NULL);
261     return 1;
262   }
263
264   case MSG_TIMEOUT:
265     XBT_DEBUG("MSG_task_send failed: timeout");
266     lua_pushnil(L);
267     lua_pushliteral(L, "timeout");
268     return 2;
269
270   case MSG_TRANSFER_FAILURE:
271     XBT_DEBUG("MSG_task_send failed: transfer failure");
272     lua_pushnil(L);
273     lua_pushliteral(L, "transfer failure");
274     return 2;
275
276   case MSG_HOST_FAILURE:
277     XBT_DEBUG("MSG_task_send failed: host failure");
278     lua_pushnil(L);
279     lua_pushliteral(L, "host failure");
280     return 2;
281
282   default:
283     xbt_die("Unexpected result of MSG_task_recv: %d, please report this bug", res);
284   }
285 }
286
287 static const luaL_reg task_functions[] = {
288   {"new", l_task_new},
289   {"get_name", l_task_get_name},
290   {"get_computation_duration", l_task_get_computation_duration},
291   {"execute", l_task_execute},
292   {"send", l_task_send},
293   {"recv", l_task_recv},
294   {NULL, NULL}
295 };
296
297 /**
298  * \brief Finalizes the userdata of a task.
299  * \param L a Lua state
300  * \return number of values returned to Lua
301  *
302  * - Argument 1 (userdata): a C task, possibly NULL if it was sent to another
303  * Lua state
304  */
305 static int l_task_gc(lua_State* L)
306 {
307                                   /* ctask */
308   m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
309   /* the task is NULL if I sent it to someone else */
310   if (task != NULL) {
311     MSG_task_destroy(task);
312   }
313   return 0;
314 }
315
316 /**
317  * \brief Returns a string representation of a C task.
318  * \param L a Lua state
319  * \return number of values returned to Lua
320  *
321  * - Argument 1 (userdata): a task
322  * - Return value (string): a string describing this task
323  */
324 static int l_task_tostring(lua_State* L)
325 {
326   m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
327   lua_pushfstring(L, "Task: %p", task);
328   return 1;
329 }
330
331 /**
332  * \brief Metamethods of both a task table and the userdata inside it.
333  */
334 static const luaL_reg task_meta[] = {
335   {"__gc", l_task_gc}, /* will be called only for userdata */
336   {"__tostring", l_task_tostring},
337   {NULL, NULL}
338 };
339
340 /* ********************************************************************************* */
341 /*                                simgrid.host API                                   */
342 /* ********************************************************************************* */
343
344 /**
345  * \brief Ensures that a value in the stack is a host and returns it.
346  * \param L a Lua state
347  * \param index an index in the Lua stack
348  * \return the C host corresponding to this Lua host
349  */
350 static m_host_t sglua_checkhost(lua_State * L, int index)
351 {
352   m_host_t *pi, ht;
353   luaL_checktype(L, index, LUA_TTABLE);
354   lua_getfield(L, index, "__simgrid_host");
355   pi = (m_host_t *) luaL_checkudata(L, lua_gettop(L), HOST_MODULE_NAME);
356   if (pi == NULL)
357     luaL_typerror(L, index, HOST_MODULE_NAME);
358   ht = *pi;
359   if (!ht)
360     luaL_error(L, "null Host");
361   lua_pop(L, 1);
362   return ht;
363 }
364
365 /**
366  * \brief Returns a host given its name.
367  * \param L a Lua state
368  * \return number of values returned to Lua
369  *
370  * - Argument 1 (string): name of a host
371  * - Return value (host): the corresponding host
372  */
373 static int l_host_get_by_name(lua_State * L)
374 {
375   const char *name = luaL_checkstring(L, 1);
376   XBT_DEBUG("Getting Host from name...");
377   m_host_t msg_host = MSG_get_host_by_name(name);
378   if (!msg_host) {
379     luaL_error(L, "null Host : MSG_get_host_by_name failed");
380   }
381   lua_newtable(L);              /* create a table, put the userdata on top of it */
382   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
383   *lua_host = msg_host;
384   luaL_getmetatable(L, HOST_MODULE_NAME);
385   lua_setmetatable(L, -2);
386   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
387   /* remove the args from the stack */
388   lua_remove(L, 1);
389   return 1;
390 }
391
392 /**
393  * \brief Returns the name of a host.
394  * \param L a Lua state
395  * \return number of values returned to Lua
396  *
397  * - Argument 1 (host): a host
398  * - Return value (string): name of this host
399  */
400 static int l_host_get_name(lua_State * L)
401 {
402   m_host_t ht = sglua_checkhost(L, 1);
403   lua_pushstring(L, MSG_host_get_name(ht));
404   return 1;
405 }
406
407 /**
408  * \brief Returns the number of existing hosts.
409  * \param L a Lua state
410  * \return number of values returned to Lua
411  *
412  * - Return value (number): number of hosts
413  */
414 static int l_host_number(lua_State * L)
415 {
416   lua_pushnumber(L, MSG_get_host_number());
417   return 1;
418 }
419
420 /**
421  * \brief Returns the host given its index.
422  * \param L a Lua state
423  * \return number of values returned to Lua
424  *
425  * - Argument 1 (number): an index (1 is the first)
426  * - Return value (host): the host at this index
427  */
428 static int l_host_at(lua_State * L)
429 {
430   int index = luaL_checkinteger(L, 1);
431   m_host_t host = MSG_get_host_table()[index - 1];      // lua indexing start by 1 (lua[1] <=> C[0])
432   lua_newtable(L);              /* create a table, put the userdata on top of it */
433   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
434   *lua_host = host;
435   luaL_getmetatable(L, HOST_MODULE_NAME);
436   lua_setmetatable(L, -2);
437   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
438   return 1;
439 }
440
441 /**
442  * \brief Returns the host where the current process is located.
443  * \param L a Lua state
444  * \return number of values returned to Lua
445  *
446  * - Return value (host): the current host
447  */
448 static int l_host_self(lua_State * L)
449 {
450                                   /* -- */
451   m_host_t host = MSG_host_self();
452   lua_newtable(L);
453                                   /* table */
454   m_host_t* lua_host = (m_host_t*) lua_newuserdata(L, sizeof(m_host_t));
455                                   /* table ud */
456   *lua_host = host;
457   luaL_getmetatable(L, HOST_MODULE_NAME);
458                                   /* table ud mt */
459   lua_setmetatable(L, -2);
460                                   /* table ud */
461   lua_setfield(L, -2, "__simgrid_host");
462                                   /* table */
463   return 1;
464 }
465
466 /**
467  * \brief Returns the value of a host property.
468  * \param L a Lua state
469  * \return number of values returned to Lua
470  *
471  * - Argument 1 (host): a host
472  * - Argument 2 (string): name of the property to get
473  * - Return value (string): the value of this property
474  */
475 static int l_host_get_property_value(lua_State * L)
476 {
477   m_host_t ht = sglua_checkhost(L, 1);
478   const char *prop = luaL_checkstring(L, 2);
479   lua_pushstring(L,MSG_host_get_property_value(ht,prop));
480   return 1;
481 }
482
483 /**
484  * \brief Makes the current process sleep for a while.
485  * \param L a Lua state
486  * \return number of values returned to Lua
487  *
488  * - Argument 1 (number): duration of the sleep
489  */
490 static int l_host_sleep(lua_State *L)
491 {
492   int time = luaL_checknumber(L, 1);
493   MSG_process_sleep(time);
494   return 0;
495 }
496
497 /**
498  * \brief Destroys a host.
499  * \param L a Lua state
500  * \return number of values returned to Lua
501  *
502  * - Argument 1 (host): the host to destroy
503  */
504 static int l_host_destroy(lua_State *L)
505 {
506   m_host_t ht = sglua_checkhost(L, 1);
507   __MSG_host_destroy(ht);
508   return 0;
509 }
510
511 static const luaL_reg host_functions[] = {
512   {"get_by_name", l_host_get_by_name},
513   {"name", l_host_get_name},
514   {"number", l_host_number},
515   {"at", l_host_at},
516   {"self", l_host_self},
517   {"get_prop_value", l_host_get_property_value},
518   {"sleep", l_host_sleep},
519   {"destroy", l_host_destroy},
520   // Bypass XML Methods
521   {"set_function", console_set_function},
522   {"set_property", console_host_set_property},
523   {NULL, NULL}
524 };
525
526 /**
527  * \brief Returns a string representation of a host.
528  * \param L a Lua state
529  * \return number of values returned to Lua
530  *
531  * - Argument 1 (userdata): a host
532  * - Return value (string): a string describing this host
533  */
534 static int l_host_tostring(lua_State * L)
535 {
536   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
537   return 1;
538 }
539
540 static const luaL_reg host_meta[] = {
541   {"__tostring", l_host_tostring},
542   {0, 0}
543 };
544
545 /* ********************************************************************************* */
546 /*                           lua_stub_generator functions                            */
547 /* ********************************************************************************* */
548
549 xbt_dict_t process_function_set;
550 xbt_dynar_t process_list;
551 xbt_dict_t machine_set;
552 static s_process_t process;
553
554 void s_process_free(void *process)
555 {
556   s_process_t *p = (s_process_t *) process;
557   int i;
558   for (i = 0; i < p->argc; i++)
559     free(p->argv[i]);
560   free(p->argv);
561   free(p->host);
562 }
563
564 static int gras_add_process_function(lua_State * L)
565 {
566   const char *arg;
567   const char *process_host = luaL_checkstring(L, 1);
568   const char *process_function = luaL_checkstring(L, 2);
569
570   if (xbt_dict_is_empty(machine_set)
571       || xbt_dict_is_empty(process_function_set)
572       || xbt_dynar_is_empty(process_list)) {
573     process_function_set = xbt_dict_new();
574     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
575     machine_set = xbt_dict_new();
576   }
577
578   xbt_dict_set(machine_set, process_host, NULL, NULL);
579   xbt_dict_set(process_function_set, process_function, NULL, NULL);
580
581   process.argc = 1;
582   process.argv = xbt_new(char *, 1);
583   process.argv[0] = xbt_strdup(process_function);
584   process.host = strdup(process_host);
585
586   lua_pushnil(L);
587   while (lua_next(L, 3) != 0) {
588     arg = lua_tostring(L, -1);
589     process.argc++;
590     process.argv =
591         xbt_realloc(process.argv, (process.argc) * sizeof(char *));
592     process.argv[(process.argc) - 1] = xbt_strdup(arg);
593
594     XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
595            lua_tostring(L, -1));
596     lua_pop(L, 1);
597   }
598   lua_pop(L, 1);
599   //add to the process list
600   xbt_dynar_push(process_list, &process);
601   return 0;
602 }
603
604 static int gras_generate(lua_State * L)
605 {
606   const char *project_name = luaL_checkstring(L, 1);
607   generate_sim(project_name);
608   generate_rl(project_name);
609   generate_makefile_local(project_name);
610   return 0;
611 }
612
613 /* ********************************************************************************* */
614 /*                               simgrid.platf API                                   */
615 /* ********************************************************************************* */
616
617 static const luaL_reg platf_functions[] = {
618     {"open", console_open},
619     {"close", console_close},
620     {"AS_open", console_AS_open},
621     {"AS_close", console_AS_close},
622     {"host_new", console_add_host},
623     {"link_new", console_add_link},
624     {"router_new", console_add_router},
625     {"route_new", console_add_route},
626     {NULL, NULL}
627 };
628
629 /* ********************************************************************************* */
630 /*                                  simgrid API                                      */
631 /* ********************************************************************************* */
632
633 /**
634  * \brief Deploys your application.
635  * \param L a Lua state
636  * \return number of values returned to Lua
637  *
638  * - Argument 1 (string): name of the deployment file to load
639  */
640 static int launch_application(lua_State * L)
641 {
642   const char *file = luaL_checkstring(L, 1);
643   MSG_function_register_default(run_lua_code);
644   MSG_launch_application(file);
645   return 0;
646 }
647
648 /**
649  * \brief Creates the platform.
650  * \param L a Lua state
651  * \return number of values returned to Lua
652  *
653  * - Argument 1 (string): name of the platform file to load
654  */
655 static int create_environment(lua_State * L)
656 {
657   const char *file = luaL_checkstring(L, 1);
658   XBT_DEBUG("Loading environment file %s", file);
659   MSG_create_environment(file);
660   return 0;
661 }
662
663 /**
664  * \brief Prints a log string with debug level.
665  * \param L a Lua state
666  * \return number of values returned to Lua
667  *
668  * - Argument 1 (string): the text to print
669  */
670 static int debug(lua_State * L)
671 {
672   const char *str = luaL_checkstring(L, 1);
673   XBT_DEBUG("%s", str);
674   return 0;
675 }
676
677 /**
678  * \brief Prints a log string with info level.
679  * \param L a Lua state
680  * \return number of values returned to Lua
681  *
682  * - Argument 1 (string): the text to print
683  */
684 static int info(lua_State * L)
685 {
686   const char *str = luaL_checkstring(L, 1);
687   XBT_INFO("%s", str);
688   return 0;
689 }
690
691 /**
692  * \brief Runs your application.
693  * \param L a Lua state
694  * \return number of values returned to Lua
695  */
696 static int run(lua_State * L)
697 {
698   MSG_main();
699   return 0;
700 }
701
702 /**
703  * \brief Cleans the simulation.
704  * \param L a Lua state
705  * \return number of values returned to Lua
706  */
707 static int simgrid_gc(lua_State * L)
708 {
709   MSG_clean();
710   return 0;
711 }
712
713 /*
714  * Register platform for MSG
715  */
716 static int msg_register_platform(lua_State * L)
717 {
718   /* Tell Simgrid we dont wanna use its parser */
719   //surf_parse = console_parse_platform;
720   surf_parse_reset_callbacks();
721   MSG_create_environment(NULL);
722   return 0;
723 }
724
725 /*
726  * Register platform for Simdag
727  */
728
729 static int sd_register_platform(lua_State * L)
730 {
731   //surf_parse = console_parse_platform_wsL07;
732   surf_parse_reset_callbacks();
733   SD_create_environment(NULL);
734   return 0;
735 }
736
737 /*
738  * Register platform for gras
739  */
740 static int gras_register_platform(lua_State * L)
741 {
742   //surf_parse = console_parse_platform;
743   surf_parse_reset_callbacks();
744   gras_create_environment(NULL);
745   return 0;
746 }
747
748 /**
749  * Register applicaiton for MSG
750  */
751 static int msg_register_application(lua_State * L)
752 {
753   MSG_function_register_default(run_lua_code);
754   //surf_parse = console_parse_application;
755   MSG_launch_application(NULL);
756   return 0;
757 }
758
759 /*
760  * Register application for gras
761  */
762 static int gras_register_application(lua_State * L)
763 {
764   gras_function_register_default(run_lua_code);
765   //surf_parse = console_parse_application;
766   gras_launch_application(NULL);
767   return 0;
768 }
769
770 static const luaL_Reg simgrid_functions[] = {
771   {"create_environment", create_environment},
772   {"launch_application", launch_application},
773   {"debug", debug},
774   {"info", info},
775   {"run", run},
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 Registers the task functions into the table simgrid.task.
875  *
876  * Also initialize the metatable of the task userdata type.
877  *
878  * \param L a lua state
879  */
880 static void register_task_functions(lua_State* L)
881 {
882   /* create a table simgrid.task and fill it with task functions */
883   luaL_openlib(L, TASK_MODULE_NAME, task_functions, 0);
884                                   /* simgrid.task */
885
886   /* create the metatable for tasks, add it to the Lua registry */
887   luaL_newmetatable(L, TASK_MODULE_NAME);
888                                   /* simgrid.task mt */
889   /* fill the metatable */
890   luaL_openlib(L, NULL, task_meta, 0);
891                                   /* simgrid.task mt */
892   lua_pushvalue(L, -2);
893                                   /* simgrid.task mt simgrid.task */
894   /* metatable.__index = simgrid.task
895    * we put the task functions inside the task itself:
896    * this allows to write task:method(args) for
897    * simgrid.task.method(task, args) */
898   lua_setfield(L, -2, "__index");
899                                   /* simgrid.task mt */
900   lua_pop(L, 2);
901                                   /* -- */
902 }
903
904 /**
905  * \brief Registers the host functions into the table simgrid.host.
906  *
907  * Also initialize the metatable of the host userdata type.
908  *
909  * \param L a lua state
910  */
911 static void register_host_functions(lua_State* L)
912 {
913   /* create a table simgrid.host and fill it with host functions */
914   luaL_openlib(L, HOST_MODULE_NAME, host_functions, 0);
915                                   /* simgrid.host */
916
917   /* create the metatable for host, add it to the Lua registry */
918   luaL_newmetatable(L, HOST_MODULE_NAME);
919                                   /* simgrid.host mt */
920   /* fill the metatable */
921   luaL_openlib(L, NULL, host_meta, 0);
922                                   /* simgrid.host mt */
923   lua_pushvalue(L, -2);
924                                   /* simgrid.host mt simgrid.host */
925   /* metatable.__index = simgrid.host
926    * we put the host functions inside the host userdata itself:
927    * this allows to write host(args) for
928    * simgrid.host.method(host, args) */
929   // FIXME: cannot work currently, same problem as tasks
930   lua_setfield(L, -2, "__index");
931                                   /* simgrid.host mt */
932   lua_pop(L, 2);
933                                   /* -- */
934 }
935
936 /**
937  * \brief Registers the platform functions into the table simgrid.platf.
938  * \param L a lua state
939  */
940 static void register_platf_functions(lua_State* L)
941 {
942   luaL_openlib(L, PLATF_MODULE_NAME, platf_functions, 0);
943                                   /* simgrid.platf */
944   lua_pop(L, 1);
945 }
946
947 /**
948  * \brief Makes the core functions available to the Lua world.
949  * \param L a Lua world
950  */
951 static void register_core_functions(lua_State *L)
952 {
953   /* register the core C functions to lua */
954   luaL_register(L, "simgrid", simgrid_functions);
955                                   /* simgrid */
956
957   /* set a finalizer that cleans simgrid, by adding to the simgrid module a
958    * dummy userdata whose __gc metamethod calls MSG_clean() */
959   lua_newuserdata(L, sizeof(void*));
960                                   /* simgrid udata */
961   lua_newtable(L);
962                                   /* simgrid udata mt */
963   lua_pushcfunction(L, simgrid_gc);
964                                   /* simgrid udata mt simgrid_gc */
965   lua_setfield(L, -2, "__gc");
966                                   /* simgrid udata mt */
967   lua_setmetatable(L, -2);
968                                   /* simgrid udata */
969   lua_setfield(L, -2, "__simgrid_loaded");
970                                   /* simgrid */
971   lua_pop(L, 1);
972                                   /* -- */
973 }
974
975 /**
976  * \brief Creates the simgrid module and make it available to Lua.
977  * \param L a Lua world
978  */
979 static void register_c_functions(lua_State *L)
980 {
981   register_core_functions(L);
982   register_task_functions(L);
983   register_host_functions(L);
984   register_platf_functions(L);
985 }
986
987 /**
988  * \brief Runs a Lua function as a new simulated process.
989  * \param argc number of arguments of the function
990  * \param argv name of the Lua function and array of its arguments
991  * \return result of the function
992  */
993 static int run_lua_code(int argc, char **argv)
994 {
995   XBT_DEBUG("Run lua code %s", argv[0]);
996
997   /* create a new state, getting globals from maestro */
998   lua_State *L = sglua_clone_maestro();
999   int res = 1;
1000
1001   /* start the function */
1002   lua_getglobal(L, argv[0]);
1003   xbt_assert(lua_isfunction(L, -1),
1004               "There is no Lua function with name `%s'", argv[0]);
1005
1006   /* push arguments onto the stack */
1007   int i;
1008   for (i = 1; i < argc; i++)
1009     lua_pushstring(L, argv[i]);
1010
1011   /* call the function */
1012   _XBT_GNUC_UNUSED int err;
1013   err = lua_pcall(L, argc - 1, 1, 0);
1014   xbt_assert(err == 0, "Error running function `%s': %s", argv[0],
1015               lua_tostring(L, -1));
1016
1017   /* retrieve result */
1018   if (lua_isnumber(L, -1)) {
1019     res = lua_tonumber(L, -1);
1020     lua_pop(L, 1);              /* pop returned value */
1021   }
1022
1023   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
1024
1025   return res;
1026 }