/** * @brief Dumps a lua table with XBT_DEBUG * * This function can be called from within lua via "simgrid.dump(table)". It will * then dump the table via XBT_DEBUG */ static int dump(lua_State* L) { int argc = lua_gettop(L); for (int i = 1; i <= argc; i++) { if (lua_istable(L, i)) { lua_pushnil(L); /* table nil */ //lua_next pops the topmost element from the stack and //gets the next pair from the table at the specified index while (lua_next(L, i)) { /* table key val */ // we need to copy here, as a cast from "Number" to "String" // could happen in Lua. // see remark in the lua manual, function "lua_tolstring" // http://www.lua.org/manual/5.3/manual.html#lua_tolstring lua_pushvalue(L, -2); /* table key val key */ XBT_DEBUG("%s", sglua_keyvalue_tostring(L, -1, -2)); } lua_settop(L, argc); // Remove everything except the initial arguments } } return 0; }
/** * @brief Copies the table value on top of src to the top of dst. * * A deep copy of the table is made. If the table has a metatable, the * metatable is also copied. * If the table comes from maestro and is already known by the destination * state, it is not copied again. * * @param src source state * @param dst destination state */ static void sglua_copy_table(lua_State* src, lua_State* dst) { /* src: ... table dst: ... */ int indent = lua_gettop(dst) * 6 + 2; /* get from maestro the pointer that identifies this table */ void* table_ptr = sglua_get_maestro_table_ptr(src, -1); int known_by_maestro = (table_ptr != NULL); if (!known_by_maestro) { /* the table didn't come from maestro: nevermind, use the pointer of src */ table_ptr = (void*) lua_topointer(src, -1); XBT_DEBUG("%sMaestro does not know this table", sglua_get_spaces(indent)); } if (sglua_is_maestro(src)) { /* register the table in maestro itself */ XBT_DEBUG("%sKeeping track of this table in maestro itself", sglua_get_spaces(indent)); sglua_add_maestro_table(src, -1, table_ptr); known_by_maestro = 1; xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr); } /* to avoid infinite recursion, see if this table is already known by dst */ sglua_get_table_by_ptr(dst, table_ptr); /* dst: ... table/nil */ if (!lua_isnil(dst, -1)) { XBT_DEBUG("%sNothing to do: table already known (%p)", sglua_get_spaces(indent), table_ptr); /* dst: ... table */ } else { XBT_DEBUG("%sFirst visit of this table (%p)", sglua_get_spaces(indent), table_ptr); /* dst: ... nil */ lua_pop(dst, 1); /* dst: ... */ /* first visit: create the new table in dst */ lua_newtable(dst); /* dst: ... table */ /* mark the table as known right now to avoid infinite recursion */ sglua_add_maestro_table(dst, -1, table_ptr); /* we may have added a table with a non-maestro pointer, but if it was the * case, we will remove it later */ XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent)); xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr); sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst); /* copy the metatable if any */ int has_meta_table = lua_getmetatable(src, -1); /* src: ... table mt? */ if (has_meta_table) { XBT_DEBUG("%sCopying the metatable", sglua_get_spaces(indent)); /* src: ... table mt */ sglua_copy_table(src, dst); /* dst: ... table mt */ lua_pop(src, 1); /* src: ... table */ lua_setmetatable(dst, -2); /* dst: ... table */ } else { /* src: ... table */ XBT_DEBUG("%sNo metatable", sglua_get_spaces(indent)); } sglua_stack_dump("src before traversing the table (should be ... table): ", src); sglua_stack_dump("dst before traversing the table (should be ... table): ", dst); /* traverse the table of src and copy each element */ lua_pushnil(src); /* src: ... table nil */ while (lua_next(src, -2) != 0) { /* src: ... table key value */ XBT_DEBUG("%sCopying table element %s", sglua_get_spaces(indent), sglua_keyvalue_tostring(src, -2, -1)); sglua_stack_dump("src before copying table element (should be ... table key value): ", src); sglua_stack_dump("dst before copying table element (should be ... table): ", dst); /* copy the key */ lua_pushvalue(src, -2); /* src: ... table key value key */ indent += 2; XBT_DEBUG("%sCopying the key part of the table element", sglua_get_spaces(indent)); sglua_move_value(src, dst); /* src: ... table key value dst: ... table key */ XBT_DEBUG("%sCopied the key part of the table element", sglua_get_spaces(indent)); /* copy the value */ XBT_DEBUG("%sCopying the value part of the table element", sglua_get_spaces(indent)); sglua_move_value(src, dst); /* src: ... table key dst: ... table key value */ XBT_DEBUG("%sCopied the value part of the table element", sglua_get_spaces(indent)); indent -= 2; /* set the table element */ lua_settable(dst, -3); /* dst: ... table */ /* the key stays on top of src for next iteration */ sglua_stack_dump("src before next iteration (should be ... table key): ", src); sglua_stack_dump("dst before next iteration (should be ... table): ", dst); XBT_DEBUG("%sTable element copied", sglua_get_spaces(indent)); } XBT_DEBUG("%sFinished traversing the table", sglua_get_spaces(indent)); } if (!known_by_maestro) { /* actually,it was not a maestro table: forget the pointer */ sglua_remove_maestro_table(dst, -1, table_ptr); } }