1 /* Copyright (c) 2010. The SimGrid Team.
2 * All rights reserved. */
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. */
7 /* SimGrid Lua bindings */
9 #include "simgrid_lua.h"
10 #include "lua_state_cloner.h"
11 #include "lua_utils.h"
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
15 #define TASK_MODULE_NAME "simgrid.task"
16 #define HOST_MODULE_NAME "simgrid.host"
18 #define LINK_MODULE_NAME "simgrid.link"
19 #define ROUTE_MODULE_NAME "simgrid.route"
20 #define PLATF_MODULE_NAME "simgrid.platf"
22 static lua_State* sglua_maestro_state;
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);
28 /* ********************************************************************************* */
29 /* simgrid.task API */
30 /* ********************************************************************************* */
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
38 static m_task_t sglua_checktask(lua_State* L, int index)
40 sglua_stack_dump("check task: ", L);
41 luaL_checktype(L, index, LUA_TTABLE);
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));
50 luaL_error(L, "This task was sent to someone else, you cannot access it anymore");
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
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
66 static int l_task_new(lua_State* L)
68 XBT_DEBUG("Task new");
69 const char* name = luaL_checkstring(L, 1);
70 int comp_size = luaL_checkint(L, 2);
71 int msg_size = luaL_checkint(L, 3);
75 m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
79 m_task_t* lua_task = (m_task_t*) lua_newuserdata(L, sizeof(m_task_t));
82 luaL_getmetatable(L, TASK_MODULE_NAME);
84 lua_setmetatable(L, -2);
86 lua_setfield(L, -2, "__simgrid_task");
92 * \brief Returns the name of a task.
93 * \param L a Lua state
94 * \return number of values returned to Lua
96 * - Argument 1 (task): a task
97 * - Return value (string): name of the task
99 static int l_task_get_name(lua_State* L)
101 m_task_t task = sglua_checktask(L, 1);
102 lua_pushstring(L, MSG_task_get_name(task));
107 * \brief Returns the computation duration of a task.
108 * \param L a Lua state
109 * \return number of values returned to Lua
111 * - Argument 1 (task): a task
112 * - Return value (number): computation duration of this task
114 static int l_task_computation_duration(lua_State* L)
116 m_task_t task = sglua_checktask(L, 1);
117 lua_pushnumber(L, MSG_task_get_compute_duration(task));
122 * \brief Executes a task.
123 * \param L a Lua state
124 * \return number of values returned to Lua
126 * - Argument 1 (task): the task to execute
127 * - Return value (number): error code
129 static int l_task_execute(lua_State* L)
131 m_task_t task = sglua_checktask(L, 1);
132 int res = MSG_task_execute(task);
133 lua_pushnumber(L, res);
138 * \brief Sends a task to a mailbox and waits for its completion.
139 * \param L a Lua state
140 * \return number of values returned to Lua
142 * - Argument 1 (task): the task to send
143 * - Argument 2 (string): mailbox
145 static int l_task_send(lua_State* L)
147 m_task_t task = sglua_checktask(L, 1);
148 const char* mailbox = luaL_checkstring(L, 2);
152 /* copy my stack into the task, so that the receiver can copy the lua task */
153 MSG_task_set_data(task, L);
154 MSG_error_t res = MSG_task_send(task, mailbox);
155 while (MSG_task_get_data(task) != NULL) {
156 /* don't mess up with my stack: the receiver didn't copy the data yet */
157 MSG_process_sleep(0);
161 /* the receiver is the owner of the task and may destroy it:
162 * remove the C task on my side so that I don't garbage collect it */
163 lua_getfield(L, 1, "__simgrid_task");
165 m_task_t* udata = (m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME);
173 XBT_DEBUG("MSG_task_send failed : Timeout");
175 case MSG_TRANSFER_FAILURE:
176 XBT_DEBUG("MSG_task_send failed : Transfer Failure");
178 case MSG_HOST_FAILURE:
179 XBT_DEBUG("MSG_task_send failed : Host Failure ");
183 ("MSG_task_send failed : Unexpected error , please report this bug");
191 * \brief Receives a task.
192 * \param L a Lua state
193 * \return number of values returned to Lua
195 * - Argument 1 (string): mailbox
196 * - Argument 2 (number, optional): timeout (default is no timeout)
197 * - Return value (task/nil): the task received or nil if the communication
200 static int l_task_recv(lua_State *L)
202 m_task_t task = NULL;
203 const char* mailbox = luaL_checkstring(L, 1);
205 if (lua_gettop(L) >= 2) {
206 /* mailbox timeout */
207 timeout = luaL_checknumber(L, 2);
212 /* no timeout by default */
216 MSG_error_t res = MSG_task_receive_with_timeout(&task, mailbox, timeout);
219 /* copy the data directly from sender's stack */
220 lua_State* sender_stack = MSG_task_get_data(task);
221 sglua_copy_value(sender_stack, L);
223 MSG_task_set_data(task, NULL);
228 XBT_DEBUG("MSG_task_receive failed : Timeout");
230 case MSG_TRANSFER_FAILURE:
231 XBT_DEBUG("MSG_task_receive failed : Transfer Failure");
233 case MSG_HOST_FAILURE:
234 XBT_DEBUG("MSG_task_receive failed : Host Failure ");
237 XBT_ERROR("MSG_task_receive failed : Unexpected error , please report this bug");
247 static const luaL_reg task_functions[] = {
249 {"name", l_task_get_name},
250 {"computation_duration", l_task_computation_duration},
251 {"execute", l_task_execute},
252 {"send", l_task_send},
253 {"recv", l_task_recv},
258 * \brief Finalizes the userdata of a task.
259 * \param L a Lua state
260 * \return number of values returned to Lua
262 * - Argument 1 (userdata): a C task, possibly NULL if it was sent to another
265 static int l_task_gc(lua_State* L)
268 m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
269 /* the task is NULL if I sent it to someone else */
271 MSG_task_destroy(task);
277 * \brief Returns a string representation of a C task.
278 * \param L a Lua state
279 * \return number of values returned to Lua
281 * - Argument 1 (userdata): a task
282 * - Return value (string): a string describing this task
284 static int l_task_tostring(lua_State* L)
286 m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
287 lua_pushfstring(L, "Task: %p", task);
291 static const luaL_reg task_meta[] = {
293 {"__tostring", l_task_tostring},
297 /* ********************************************************************************* */
298 /* simgrid.host API */
299 /* ********************************************************************************* */
302 * \brief Ensures that a value in the stack is a host and returns it.
303 * \param L a Lua state
304 * \param index an index in the Lua stack
305 * \return the C host corresponding to this Lua host
307 static m_host_t sglua_checkhost(lua_State * L, int index)
310 luaL_checktype(L, index, LUA_TTABLE);
311 lua_getfield(L, index, "__simgrid_host");
312 pi = (m_host_t *) luaL_checkudata(L, lua_gettop(L), HOST_MODULE_NAME);
314 luaL_typerror(L, index, HOST_MODULE_NAME);
317 luaL_error(L, "null Host");
323 * \brief Returns a host given its name.
324 * \param L a Lua state
325 * \return number of values returned to Lua
327 * - Argument 1 (string): name of a host
328 * - Return value (host): the corresponding host
330 static int l_host_get_by_name(lua_State * L)
332 const char *name = luaL_checkstring(L, 1);
333 XBT_DEBUG("Getting Host from name...");
334 m_host_t msg_host = MSG_get_host_by_name(name);
336 luaL_error(L, "null Host : MSG_get_host_by_name failed");
338 lua_newtable(L); /* create a table, put the userdata on top of it */
339 m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
340 *lua_host = msg_host;
341 luaL_getmetatable(L, HOST_MODULE_NAME);
342 lua_setmetatable(L, -2);
343 lua_setfield(L, -2, "__simgrid_host"); /* put the userdata as field of the table */
344 /* remove the args from the stack */
350 * \brief Returns the name of a host.
351 * \param L a Lua state
352 * \return number of values returned to Lua
354 * - Argument 1 (host): a host
355 * - Return value (string): name of this host
357 static int l_host_get_name(lua_State * L)
359 m_host_t ht = sglua_checkhost(L, 1);
360 lua_pushstring(L, MSG_host_get_name(ht));
365 * \brief Returns the number of existing hosts.
366 * \param L a Lua state
367 * \return number of values returned to Lua
369 * - Return value (number): number of hosts
371 static int l_host_number(lua_State * L)
373 lua_pushnumber(L, MSG_get_host_number());
378 * \brief Returns the host given its index.
379 * \param L a Lua state
380 * \return number of values returned to Lua
382 * - Argument 1 (number): an index (1 is the first)
383 * - Return value (host): the host at this index
385 static int l_host_at(lua_State * L)
387 int index = luaL_checkinteger(L, 1);
388 m_host_t host = MSG_get_host_table()[index - 1]; // lua indexing start by 1 (lua[1] <=> C[0])
389 lua_newtable(L); /* create a table, put the userdata on top of it */
390 m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
392 luaL_getmetatable(L, HOST_MODULE_NAME);
393 lua_setmetatable(L, -2);
394 lua_setfield(L, -2, "__simgrid_host"); /* put the userdata as field of the table */
399 * \brief Returns the host where the current process is located.
400 * \param L a Lua state
401 * \return number of values returned to Lua
403 * - Return value (host): the current host
405 static int l_host_self(lua_State * L)
408 m_host_t host = MSG_host_self();
411 m_host_t* lua_host = (m_host_t*) lua_newuserdata(L, sizeof(m_host_t));
414 luaL_getmetatable(L, HOST_MODULE_NAME);
416 lua_setmetatable(L, -2);
418 lua_setfield(L, -2, "__simgrid_host");
424 * \brief Returns the value of a host property.
425 * \param L a Lua state
426 * \return number of values returned to Lua
428 * - Argument 1 (host): a host
429 * - Argument 2 (string): name of the property to get
430 * - Return value (string): the value of this property
432 static int l_host_get_property_value(lua_State * L)
434 m_host_t ht = sglua_checkhost(L, 1);
435 const char *prop = luaL_checkstring(L, 2);
436 lua_pushstring(L,MSG_host_get_property_value(ht,prop));
441 * \brief Makes the current process sleep for a while.
442 * \param L a Lua state
443 * \return number of values returned to Lua
445 * - Argument 1 (number): duration of the sleep
447 static int l_host_sleep(lua_State *L)
449 int time = luaL_checknumber(L, 1);
450 MSG_process_sleep(time);
455 * \brief Destroys a host.
456 * \param L a Lua state
457 * \return number of values returned to Lua
459 * - Argument 1 (host): the host to destroy
461 static int l_host_destroy(lua_State *L)
463 m_host_t ht = sglua_checkhost(L, 1);
464 __MSG_host_destroy(ht);
468 static const luaL_reg host_functions[] = {
469 {"get_by_name", l_host_get_by_name},
470 {"name", l_host_get_name},
471 {"number", l_host_number},
473 {"self", l_host_self},
474 {"get_prop_value", l_host_get_property_value},
475 {"sleep", l_host_sleep},
476 {"destroy", l_host_destroy},
477 // Bypass XML Methods
478 {"set_function", console_set_function},
479 {"set_property", console_host_set_property},
484 * \brief Returns a string representation of a host.
485 * \param L a Lua state
486 * \return number of values returned to Lua
488 * - Argument 1 (userdata): a host
489 * - Return value (string): a string describing this host
491 static int l_host_tostring(lua_State * L)
493 lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
497 static const luaL_reg host_meta[] = {
498 {"__tostring", l_host_tostring},
502 /* ********************************************************************************* */
503 /* lua_stub_generator functions */
504 /* ********************************************************************************* */
506 xbt_dict_t process_function_set;
507 xbt_dynar_t process_list;
508 xbt_dict_t machine_set;
509 static s_process_t process;
511 void s_process_free(void *process)
513 s_process_t *p = (s_process_t *) process;
515 for (i = 0; i < p->argc; i++)
521 static int gras_add_process_function(lua_State * L)
524 const char *process_host = luaL_checkstring(L, 1);
525 const char *process_function = luaL_checkstring(L, 2);
527 if (xbt_dict_is_empty(machine_set)
528 || xbt_dict_is_empty(process_function_set)
529 || xbt_dynar_is_empty(process_list)) {
530 process_function_set = xbt_dict_new();
531 process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
532 machine_set = xbt_dict_new();
535 xbt_dict_set(machine_set, process_host, NULL, NULL);
536 xbt_dict_set(process_function_set, process_function, NULL, NULL);
539 process.argv = xbt_new(char *, 1);
540 process.argv[0] = xbt_strdup(process_function);
541 process.host = strdup(process_host);
544 while (lua_next(L, 3) != 0) {
545 arg = lua_tostring(L, -1);
548 xbt_realloc(process.argv, (process.argc) * sizeof(char *));
549 process.argv[(process.argc) - 1] = xbt_strdup(arg);
551 XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
552 lua_tostring(L, -1));
556 //add to the process list
557 xbt_dynar_push(process_list, &process);
561 static int gras_generate(lua_State * L)
563 const char *project_name = luaL_checkstring(L, 1);
564 generate_sim(project_name);
565 generate_rl(project_name);
566 generate_makefile_local(project_name);
570 /* ********************************************************************************* */
571 /* simgrid.platf API */
572 /* ********************************************************************************* */
574 static const luaL_reg platf_functions[] = {
575 {"open", console_open},
576 {"close", console_close},
577 {"AS_open", console_AS_open},
578 {"AS_close", console_AS_close},
579 {"host_new", console_add_host},
580 {"link_new", console_add_link},
581 {"router_new", console_add_router},
582 {"route_new", console_add_route},
586 /* ********************************************************************************* */
588 /* ********************************************************************************* */
591 * \brief Deploys your application.
592 * \param L a Lua state
593 * \return number of values returned to Lua
595 * - Argument 1 (string): name of the deployment file to load
597 static int launch_application(lua_State * L)
599 const char *file = luaL_checkstring(L, 1);
600 MSG_function_register_default(run_lua_code);
601 MSG_launch_application(file);
606 * \brief Creates the platform.
607 * \param L a Lua state
608 * \return number of values returned to Lua
610 * - Argument 1 (string): name of the platform file to load
612 static int create_environment(lua_State * L)
614 const char *file = luaL_checkstring(L, 1);
615 XBT_DEBUG("Loading environment file %s", file);
616 MSG_create_environment(file);
621 * \brief Prints a log string with debug level.
622 * \param L a Lua state
623 * \return number of values returned to Lua
625 * - Argument 1 (string): the text to print
627 static int debug(lua_State * L)
629 const char *str = luaL_checkstring(L, 1);
630 XBT_DEBUG("%s", str);
635 * \brief Prints a log string with info level.
636 * \param L a Lua state
637 * \return number of values returned to Lua
639 * - Argument 1 (string): the text to print
641 static int info(lua_State * L)
643 const char *str = luaL_checkstring(L, 1);
649 * \brief Runs your application.
650 * \param L a Lua state
651 * \return number of values returned to Lua
653 static int run(lua_State * L)
660 * \brief Cleans the simulation.
661 * \param L a Lua state
662 * \return number of values returned to Lua
664 static int simgrid_gc(lua_State * L)
671 * Register platform for MSG
673 static int msg_register_platform(lua_State * L)
675 /* Tell Simgrid we dont wanna use its parser */
676 //surf_parse = console_parse_platform;
677 surf_parse_reset_callbacks();
678 MSG_create_environment(NULL);
683 * Register platform for Simdag
686 static int sd_register_platform(lua_State * L)
688 //surf_parse = console_parse_platform_wsL07;
689 surf_parse_reset_callbacks();
690 SD_create_environment(NULL);
695 * Register platform for gras
697 static int gras_register_platform(lua_State * L)
699 //surf_parse = console_parse_platform;
700 surf_parse_reset_callbacks();
701 gras_create_environment(NULL);
706 * Register applicaiton for MSG
708 static int msg_register_application(lua_State * L)
710 MSG_function_register_default(run_lua_code);
711 //surf_parse = console_parse_application;
712 MSG_launch_application(NULL);
717 * Register application for gras
719 static int gras_register_application(lua_State * L)
721 gras_function_register_default(run_lua_code);
722 //surf_parse = console_parse_application;
723 gras_launch_application(NULL);
727 static const luaL_Reg simgrid_functions[] = {
728 {"create_environment", create_environment},
729 {"launch_application", launch_application},
734 {"platform", create_environment},
735 {"application", launch_application},
736 /* methods to bypass XML parser */
737 {"msg_register_platform", msg_register_platform},
738 {"sd_register_platform", sd_register_platform},
739 {"msg_register_application", msg_register_application},
740 {"gras_register_platform", gras_register_platform},
741 {"gras_register_application", gras_register_application},
742 /* gras sub generator method */
743 {"gras_set_process_function", gras_add_process_function},
744 {"gras_generate", gras_generate},
748 /* ********************************************************************************* */
749 /* module management functions */
750 /* ********************************************************************************* */
752 #define LUA_MAX_ARGS_COUNT 10 /* maximum amount of arguments we can get from lua on command line */
755 * \brief Opens the simgrid Lua module.
757 * This function is called automatically by the Lua interpreter when some
758 * Lua code requires the "simgrid" module.
760 * \param L the Lua state
762 int luaopen_simgrid(lua_State *L)
764 XBT_DEBUG("luaopen_simgrid *****");
766 /* Get the command line arguments from the lua interpreter */
767 char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
769 argv[0] = (char *) "/usr/bin/lua"; /* Lie on the argv[0] so that the stack dumping facilities find the right binary. FIXME: what if lua is not in that location? */
771 lua_getglobal(L, "arg");
772 /* if arg is a null value, it means we use lua only as a script to init platform
773 * else it should be a table and then take arg in consideration
775 if (lua_istable(L, -1)) {
779 lua_pushinteger(L, argc - 2);
781 if (lua_isnil(L, -1)) {
784 xbt_assert(lua_isstring(L, -1),
785 "argv[%d] got from lua is no string", argc - 1);
786 xbt_assert(argc < LUA_MAX_ARGS_COUNT,
787 "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",
788 __FILE__, LUA_MAX_ARGS_COUNT - 1);
789 argv[argc - 1] = (char *) luaL_checkstring(L, -1);
791 XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
796 /* Initialize the MSG core */
797 MSG_global_init(&argc, argv);
798 XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
801 /* Keep the context mechanism informed of our lua world today */
802 sglua_maestro_state = L;
804 /* initialize access to my tables by children Lua states */
806 lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
808 register_c_functions(L);
814 * \brief Returns whether a Lua state is the maestro state.
815 * \param L a Lua state
816 * \return true if this is maestro
818 int sglua_is_maestro(lua_State* L) {
819 return L == sglua_maestro_state;
823 * \brief Returns the maestro state.
824 * \return the maestro Lua state
826 lua_State* sglua_get_maestro(void) {
827 return sglua_maestro_state;
831 * \brief Registers the task functions into the table simgrid.task.
833 * Also initialize the metatable of the task userdata type.
835 * \param L a lua state
837 static void register_task_functions(lua_State* L)
839 /* create a table simgrid.task and fill it with task functions */
840 luaL_openlib(L, TASK_MODULE_NAME, task_functions, 0);
843 /* create the metatable for tasks, add it to the Lua registry */
844 luaL_newmetatable(L, TASK_MODULE_NAME);
845 /* simgrid.task mt */
846 /* fill the metatable */
847 luaL_openlib(L, NULL, task_meta, 0);
848 /* simgrid.task mt */
849 lua_pushvalue(L, -2);
850 /* simgrid.task mt simgrid.task */
851 /* metatable.__index = simgrid.task
852 * we put the task functions inside the task userdata itself:
853 * this allows to write task:method(args) for
854 * simgrid.task.method(task, args) */
855 // FIXME: in the current implementation, a Lua task is a table with a
856 // __simgrid_task field that contains the userdata, so the OO-style
857 // writing doesn't work
858 lua_setfield(L, -2, "__index");
859 /* simgrid.task mt */
865 * \brief Registers the host functions into the table simgrid.host.
867 * Also initialize the metatable of the host userdata type.
869 * \param L a lua state
871 static void register_host_functions(lua_State* L)
873 /* create a table simgrid.host and fill it with host functions */
874 luaL_openlib(L, HOST_MODULE_NAME, host_functions, 0);
877 /* create the metatable for host, add it to the Lua registry */
878 luaL_newmetatable(L, HOST_MODULE_NAME);
879 /* simgrid.host mt */
880 /* fill the metatable */
881 luaL_openlib(L, NULL, host_meta, 0);
882 /* simgrid.host mt */
883 lua_pushvalue(L, -2);
884 /* simgrid.host mt simgrid.host */
885 /* metatable.__index = simgrid.host
886 * we put the host functions inside the host userdata itself:
887 * this allows to write host(args) for
888 * simgrid.host.method(host, args) */
889 // FIXME: cannot work currently, same problem as tasks
890 lua_setfield(L, -2, "__index");
891 /* simgrid.host mt */
897 * \brief Registers the platform functions into the table simgrid.platf.
898 * \param L a lua state
900 static void register_platf_functions(lua_State* L)
902 luaL_openlib(L, PLATF_MODULE_NAME, platf_functions, 0);
908 * \brief Makes the core functions available to the Lua world.
909 * \param L a Lua world
911 static void register_core_functions(lua_State *L)
913 /* register the core C functions to lua */
914 luaL_register(L, "simgrid", simgrid_functions);
917 /* set a finalizer that cleans simgrid, by adding to the simgrid module a
918 * dummy userdata whose __gc metamethod calls MSG_clean() */
919 lua_newuserdata(L, sizeof(void*));
922 /* simgrid udata mt */
923 lua_pushcfunction(L, simgrid_gc);
924 /* simgrid udata mt simgrid_gc */
925 lua_setfield(L, -2, "__gc");
926 /* simgrid udata mt */
927 lua_setmetatable(L, -2);
929 lua_setfield(L, -2, "__simgrid_loaded");
936 * \brief Creates the simgrid module and make it available to Lua.
937 * \param L a Lua world
939 static void register_c_functions(lua_State *L)
941 register_core_functions(L);
942 register_task_functions(L);
943 register_host_functions(L);
944 register_platf_functions(L);
948 * \brief Runs a Lua function as a new simulated process.
949 * \param argc number of arguments of the function
950 * \param argv name of the Lua function and array of its arguments
951 * \return result of the function
953 static int run_lua_code(int argc, char **argv)
955 XBT_DEBUG("Run lua code %s", argv[0]);
957 /* create a new state, getting globals from maestro */
958 lua_State *L = sglua_clone_maestro();
961 /* start the function */
962 lua_getglobal(L, argv[0]);
963 xbt_assert(lua_isfunction(L, -1),
964 "There is no Lua function with name `%s'", argv[0]);
966 /* push arguments onto the stack */
968 for (i = 1; i < argc; i++)
969 lua_pushstring(L, argv[i]);
971 /* call the function */
972 _XBT_GNUC_UNUSED int err;
973 err = lua_pcall(L, argc - 1, 1, 0);
974 xbt_assert(err == 0, "Error running function `%s': %s", argv[0],
975 lua_tostring(L, -1));
977 /* retrieve result */
978 if (lua_isnumber(L, -1)) {
979 res = lua_tonumber(L, -1);
980 lua_pop(L, 1); /* pop returned value */
983 XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));