- if (lua_iscfunction(src, -1)) {
- /* it's a C function: just copy the pointer */
- lua_CFunction f = lua_tocfunction(src, -1);
- lua_pushcfunction(dst, f);
- }
- else {
- /* it's a Lua function: dump it from src */
- XBT_DEBUG("%sDumping Lua function '%s'", get_spaces(indent), name);
-
- s_buffer_t buffer;
- buffer.capacity = 64;
- buffer.size = 0;
- buffer.data = xbt_new(char, buffer.capacity);
-
- /* copy the binary chunk from src into a buffer */
- int error = lua_dump(src, writer, &buffer);
- xbt_assert(!error, "Failed to dump function '%s' from the source state: error %d",
- name, error);
-
- /* load the chunk into dst */
- error = luaL_loadbuffer(dst, buffer.data, buffer.size, name);
- xbt_assert(!error, "Failed to load function '%s' into the destination state: %s",
- name, lua_tostring(dst, -1));
- XBT_DEBUG("%sFunction '%s' successfully loaded", get_spaces(indent), name);
- }
- break;
-
- case LUA_TTABLE:
-
- /* see if this table was already visited */
- lua_pushlightuserdata(dst, (void*) lua_topointer(src, -1));
- /* dst: visited ... psrctable */
- lua_gettable(dst, 1);
- /* dst: visited ... table/nil */
- if (lua_istable(dst, -1)) {
- XBT_DEBUG("%sNothing to do: table already visited", get_spaces(indent));
- /* dst: visited ... table */
- }
- else {
- XBT_DEBUG("%sFirst visit of this table", get_spaces(indent));
- /* dst: visited ... nil */
- lua_pop(dst, 1);
- /* dst: visited ... */
-
- /* first visit: create the new table in dst */
- lua_newtable(dst);
- /* dst: visited ... table */
-
- /* mark the table as visited to avoid infinite recursion */
- lua_pushlightuserdata(dst, (void*) lua_topointer(src, -1));
- /* dst: visited ... table psrctable */
- lua_pushvalue(dst, -2);
- /* dst: visited ... table psrctable table */
- lua_settable(dst, 1);
- /* dst: visited ... table */
- XBT_DEBUG("%sTable marked as visited", get_spaces(indent));
-
- stack_dump("dst after marking the table as visited (should be visited ... 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 metatable", get_spaces(indent));
- /* src: ... table mt */
- move_value_impl(src, dst, "metatable");
- /* src: ... table
- dst: visited ... table mt */
- lua_setmetatable(dst, -2);
- /* dst: visited ... table */
- }
- else {
- XBT_DEBUG("%sNo metatable", get_spaces(indent));
- }
-
- stack_dump("src before traversing the table (should be ... table): ", src);
- stack_dump("dst before traversing the table (should be visited ... 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", get_spaces(indent), keyvalue_tostring(src, -2, -1));
-
- stack_dump("src before copying table element (should be ... table key value): ", src);
- stack_dump("dst before copying table element (should be visited ... 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", get_spaces(indent));
- move_value_impl(src, dst, value_tostring(src, -1));
- /* src: ... table key value
- dst: visited ... table key */
- XBT_DEBUG("%sCopied the key part of the table element", get_spaces(indent));
-
- /* copy the value */
- XBT_DEBUG("%sCopying the value part of the table element", get_spaces(indent));
- move_value_impl(src, dst, value_tostring(src, -1));
- /* src: ... table key
- dst: visited ... table key value */
- XBT_DEBUG("%sCopied the value part of the table element", get_spaces(indent));
- indent -= 2;
-
- /* set the table element */
- lua_settable(dst, -3);
- /* dst: visited ... table */
-
- /* the key stays on top of src for next iteration */
- stack_dump("src before next iteration (should be ... table key): ", src);
- stack_dump("dst before next iteration (should be visited ... table): ", dst);
-
- XBT_DEBUG("%sTable element copied", get_spaces(indent));
- }
- XBT_DEBUG("%sFinished traversing the table", get_spaces(indent));
- }
- break;
-
- case LUA_TLIGHTUSERDATA:
- lua_pushlightuserdata(dst, lua_touserdata(src, -1));
- break;
-
- case LUA_TUSERDATA:
- {
- /* copy the data */
- size_t size = lua_objlen(src, -1);
- void* src_block = lua_touserdata(src, -1);
- void* dst_block = lua_newuserdata(dst, size);
- memcpy(dst_block, src_block, size);
-
- /* copy the metatable if any */
- int has_meta_table = lua_getmetatable(src, -1);
- /* src: ... udata mt? */
- if (has_meta_table) {
- XBT_DEBUG("%sCopying metatable of userdata", get_spaces(indent));
- /* src: ... udata mt */
- move_value_impl(src, dst, "metatable");
- /* src: ... udata
- dst: visited ... udata mt */
- lua_setmetatable(dst, -2);
- /* dst: visited ... udata */
-
- XBT_DEBUG("%sMetatable of userdata copied", get_spaces(indent));
- }
- else {
- XBT_DEBUG("%sNo metatable for this userdata", get_spaces(indent));
- /* src: ... udata */
- }
- }
- break;