/** * @brief Returns a string representation of a key-value pair. * * It always returns the same pointer. * * @param L the Lua state * @param key_index index of the key (in the lua stack) * @param value_index index of the value (in the lua stack) * @return a string representation of the key-value pair */ const char* sglua_keyvalue_tostring(lua_State* L, int key_index, int value_index) { static char buff[64]; /* value_tostring also always returns the same pointer */ int len = snprintf(buff, 63, "[%s] -> ", sglua_tostring(L, key_index)); snprintf(buff + len, 63 - len, "%s", sglua_tostring(L, value_index)); return buff; }
/** * @brief Pushes onto the stack a copy of the value on top another stack. * If the value is a table, its content is copied recursively. * * This function allows to move a value between two different global states. * * @param src the source state (not necessarily maestro) * @param dst the destination state */ void sglua_copy_value(lua_State* src, lua_State* dst) { luaL_checkany(src, -1); /* check the value to copy */ int indent = (lua_gettop(dst) - 1) * 6; XBT_DEBUG("%sCopying data %s", sglua_get_spaces(indent), sglua_tostring(src, -1)); sglua_stack_dump("src before copying a value (should be ... value): ", src); sglua_stack_dump("dst before copying a value (should be ...): ", dst); switch (lua_type(src, -1)) { case LUA_TNIL: sglua_copy_nil(src, dst); break; case LUA_TNUMBER: sglua_copy_number(src, dst); break; case LUA_TBOOLEAN: sglua_copy_boolean(src, dst); break; case LUA_TSTRING: sglua_copy_string(src, dst); break; case LUA_TFUNCTION: sglua_copy_function(src, dst); break; case LUA_TTABLE: sglua_copy_table(src, dst); break; case LUA_TLIGHTUSERDATA: sglua_copy_lightuserdata(src, dst); break; case LUA_TUSERDATA: sglua_copy_userdata(src, dst); break; case LUA_TTHREAD: sglua_copy_thread(src, dst); break; } XBT_DEBUG("%sData copied", sglua_get_spaces(indent)); sglua_stack_dump("src after copying a value (should be ... value): ", src); sglua_stack_dump("dst after copying a value (should be ... value): ", dst); }
/** * @brief Copies a global value or a registry value from the maestro state. * * The state L must have been created by sglua_clone_maestro_state(). * This function is meant to be an __index metamethod. * Consequently, it assumes that the stack has two elements: * a table (either the environment or the registry of L) and the string key of * a value that does not exist yet in this table. It copies the corresponding * value from maestro and pushes it on the stack of L. * If the value does not exist in maestro state either, nil is pushed. * * TODO: make this function thread safe. If the simulation runs in parallel, * several simulated processes may trigger this __index metamethod at the same * time and get globals from maestro. * * @param L the current state * @return number of return values pushed (always 1) */ static int l_get_from_maestro(lua_State *L) { /* check the arguments */ luaL_checktype(L, 1, LUA_TTABLE); const char* key = luaL_checkstring(L, 2); /* L: table key */ XBT_DEBUG("__index of '%s' begins", key); /* want a global or a registry value? */ int pseudo_index; if (lua_equal(L, 1, LUA_REGISTRYINDEX)) { /* registry */ pseudo_index = LUA_REGISTRYINDEX; XBT_DEBUG("Will get the value from the registry of maestro"); } else { /* global */ pseudo_index = LUA_GLOBALSINDEX; XBT_DEBUG("Will get the value from the globals of maestro"); } /* get the father */ lua_State* maestro = sglua_get_maestro(); /* L: table key */ /* get the value from maestro */ lua_getfield(maestro, pseudo_index, key); /* maestro: ... value */ /* push the value onto the stack of L */ sglua_move_value(maestro, L); /* maestro: ... L: table key value */ /* prepare the return value of __index */ lua_pushvalue(L, -1); /* L: table key value value */ lua_insert(L, 1); /* L: value table key value */ /* save the copied value in the table for subsequent accesses */ lua_settable(L, -3); /* L: value table */ lua_settop(L, 1); /* L: value */ XBT_DEBUG("__index of '%s' returns %s", key, sglua_tostring(L, -1)); return 1; }
/** * @brief Dumps the Lua stack if debug logs are enabled. * @param msg a message to print * @param L a Lua state */ void sglua_stack_dump(lua_State* L, const char* msg) { if (XBT_LOG_ISENABLED(lua_debug, xbt_log_priority_debug)) { char buff[2048]; char* p = buff; int top = lua_gettop(L); fflush(stdout); p[0] = '\0'; for (int i = 1; i <= top; i++) { /* repeat for each level */ p += snprintf(p, 2048-(p-buff), "%s ", sglua_tostring(L, i)); } XBT_DEBUG("%s%s", msg, buff); } }