static int auxupvalue (lua_State *L, int get) { const char *name; int n = luaL_checkint(L, 2); luaL_checktype(L, 1, LUA_TFUNCTION); if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); if (name == NULL) return 0; lua_pushstring(L, name); lua_insert(L, -(get+1)); return get + 1; }
/* copies upvalues between lua states' stacks */ static int luaproc_copyupvalues( lua_State *Lfrom, lua_State *Lto, int funcindex ) { int i = 1; const char *str; size_t len; /* test the type of each upvalue and, if it's supported, copy it */ while ( lua_getupvalue( Lfrom, funcindex, i ) != NULL ) { switch ( lua_type( Lfrom, -1 )) { case LUA_TBOOLEAN: lua_pushboolean( Lto, lua_toboolean( Lfrom, -1 )); break; case LUA_TNUMBER: copynumber( Lto, Lfrom, -1 ); break; case LUA_TSTRING: { str = lua_tolstring( Lfrom, -1, &len ); lua_pushlstring( Lto, str, len ); break; } case LUA_TNIL: lua_pushnil( Lto ); break; /* if upvalue is a table, check whether it is the global environment (_ENV) from the source state Lfrom. in case so, push in the stack of the destination state Lto its own global environment to be set as the corresponding upvalue; otherwise, treat it as a regular non-supported upvalue type. */ case LUA_TTABLE: lua_pushglobaltable( Lfrom ); if ( isequal( Lfrom, -1, -2 )) { lua_pop( Lfrom, 1 ); lua_pushglobaltable( Lto ); break; } lua_pop( Lfrom, 1 ); /* FALLTHROUGH */ default: /* value type not supported: table, function, userdata, etc. */ lua_pushnil( Lfrom ); lua_pushfstring( Lfrom, "failed to copy upvalue of unsupported type " "'%s'", luaL_typename( Lfrom, -2 )); return FALSE; } lua_pop( Lfrom, 1 ); if ( lua_setupvalue( Lto, 1, i ) == NULL ) { lua_pushnil( Lfrom ); lua_pushstring( Lfrom, "failed to set upvalue" ); return FALSE; } i++; } return TRUE; }
static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); const char *mode = luaL_optstring(L, 2, NULL); int env = !lua_isnone(L, 3); /* 'env' parameter? */ int status = luaL_loadfilex(L, fname, mode); if (status == LUA_OK && env) { /* 'env' parameter? */ lua_pushvalue(L, 3); lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */ } return load_aux(L, status); }
void am_setfenv(lua_State *L, int index) { assert(lua_isfunction(L, index)); assert(lua_istable(L, -1)); #if defined(AM_LUAJIT) || defined(AM_LUA51) lua_setfenv(L, index); #else const char *name = lua_setupvalue(L, index, 1); assert(strcmp(name, "_ENV") == 0); AM_UNUSED(name); #endif }
static int Lcallback(lua_State *L) { ls_EventSlot *slot = checkslot(L, 1); lua_settop(L, 2); lua_pushvalue(L, 1); setcbinfo(L, slot, 4); lua_getupvalue(L, -1, UV_SELF); if (!lua_isnone(L, 2)) { lua_pushvalue(L, 2); lua_setupvalue(L, -3, UV_CB); } return 1; }
static void setcbinfo(lua_State *L, ls_EventSlot *slot, int upvalue) { lsL_getregistry(L, LS_EVENT_CBOX); /* 1 */ lua_rawgetp(L, -1, (void*)slot); /* 2 */ if (lua_isnil(L, -1)) { lua_settop(L, lua_gettop(L) + 3); /* 2,3,4,5 */ lua_pushcclosure(L, Lcb_impl, 4); /* 2,3,4,5->2 */ lua_pushvalue(L, -1); /* 2->3 */ lua_rawsetp(L, -3, (void*)slot); /* 3->1 */ } lua_remove(L, -2); /* (1) */ lua_pushvalue(L, -2); lua_setupvalue(L, -2, upvalue); }
/* ** changes the environment variable of calling function */ static void set_env(lua_State *L) { lua_Debug ar; if(lua_getstack(L, 1, &ar) == 0 || lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ lua_iscfunction(L, -1)) luaL_error(L, LUA_QL("module") " not called from a Lua function"); lua_pushvalue(L, -2); /* copy new environment table to top */ lua_setupvalue(L, -2, 1); lua_pop(L, 1); /* remove function */ }
const char * io_template_render(io_template_t *T) { lua_State *L; size_t len; char *lua_code, *lua_name; L = luaL_newstate(); luaL_openlibs(L); io_require_io(L); lua_pushlightuserdata(L, T); lua_setfield(L, LUA_REGISTRYINDEX, "io_template"); sds output = sdsempty(); lua_pushlightuserdata(L, &output); lua_setfield(L, LUA_REGISTRYINDEX, "io_output"); lua_code = T->code; lua_name = T->name; if (luaL_loadbuffer(L, lua_code, strlen(lua_code), lua_name) == LUA_OK) { // stash = ... io_object_to_lua_stack(T->stash, L); // stash_mt = { __index = _G } lua_newtable(L); lua_pushinteger(L, LUA_RIDX_GLOBALS); lua_gettable(L, LUA_REGISTRYINDEX); lua_setfield(L, -2, "__index"); // setmetatable(stash, stash_mt) lua_setmetatable(L, -2); // Set environment and call function. lua_setupvalue(L, -2, 1); lua_pcall(L, 0, 0, 0); } else { fprintf(stderr, "Error: %s\n", lua_tostring(L, -1)); } len = sdslen(output); free(T->last_render); T->last_render = malloc(sizeof(char) * (len+1)); strncpy(T->last_render, output, len+1); sdsfree(output); lua_close(L); return T->last_render; }
static int Ldeleteslot(lua_State *L) { ls_EventSlot **pslot = testslot(L, 1); if (pslot && *pslot) { ls_event_disconnect(*pslot); lua_pushnil(L); setcbinfo(L, *pslot, UV_SIGN); lua_pushnil(L); lua_setupvalue(L, -2, UV_SELF); lua_pushnil(L); lua_setmetatable(L, 1); *pslot = NULL; } return 0; }
static int luahtml_load(lua_State *L) { struct luahtml_readdata rd; const char *outfunc = luaL_checkstring(L, 2); const char *chunkname = luaL_checkstring(L, 3); int res; if (lua_isuserdata(L, 1)) { rd.utf8.file = luahtml_tofile(L); rd.utf8.readchar = luahtml_readfile; } else { rd.utf8.src = (unsigned char *) lua_tolstring(L, 1, &rd.utf8.srclen); rd.utf8.readchar = luahtml_readstring; } rd.utf8.accu = 0; rd.utf8.numa = 0; rd.utf8.bufc = -1; rd.code_present = 0; rd.state = PARSER_UNDEF; strcpy((char *) rd.buf0, " "); strcat((char *) rd.buf0, outfunc); strcat((char *) rd.buf0, "("); rd.buf = rd.buf0 + strlen((char *) rd.buf0); #if LUA_VERSION_NUM < 502 res = lua_load(L, luahtml_readparsed, &rd, chunkname); #else res = lua_load(L, luahtml_readparsed, &rd, chunkname, NULL); #endif if (res == 0) { #if LUA_VERSION_NUM >= 502 lua_pushvalue(L, 4); lua_setupvalue(L, -2, 1); #endif lua_pushboolean(L, rd.code_present); return 2; } lua_pushnil(L); lua_insert(L, -2); /* nil, message on stack */ return 2; }
static int debug_getupvalue(lua_State *L, int get) { int32_t n = lj_lib_checkint(L, 2); if (isluafunc(lj_lib_checkfunc(L, 1))) { const char *name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); if (name) { lua_pushstring(L, name); if (!get) return 1; copyTV(L, L->top, L->top-2); L->top++; return 2; } } return 0; }
static int load_aux (lua_State *L, int status, int envidx) { if (status == LUA_OK) { if (envidx != 0) { /* 'env' parameter? */ lua_pushvalue(L, envidx); /* environment for loaded function */ if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ lua_pop(L, 1); /* remove 'env' if not used by previous call */ } return 1; } else { /* error (message is on top of the stack) */ lua_pushnil(L); lua_insert(L, -2); /* put before error message */ return 2; /* return nil plus error message */ } }
static int console_autoexec(lua_State* l) { LUA_DEBUG_START(l); init_global_table(l); // _ENV LuaConsole *c = static_cast<LuaConsole *>(lua_touserdata(l, lua_upvalueindex(1))); RefCountedPtr<FileSystem::FileData> code = FileSystem::userFiles.ReadFile("console.lua"); if (!code) { lua_pop(l, 1); LUA_DEBUG_END(l, 0); return 0; } int ret = pi_lua_loadfile(l, *code); // code, _ENV if (ret != LUA_OK) { if (ret == LUA_ERRSYNTAX) { const char *msg = lua_tostring(l, -1); Output("console.lua: %s\n", msg); lua_pop(l, 1); } c->AddOutput("Failed to run console.lua"); lua_pop(l, 1); //popping _ENV LUA_DEBUG_END(l, 0); return 0; } // set the chunk's _ENV (globals) var lua_insert(l, -2); // _ENV, code lua_setupvalue(l, -2, 1); // code lua_pushcfunction(l, &capture_traceback); // traceback, code lua_insert(l, -2); // code, traceback ret = lua_pcall(l, 0, 0, -2); if (ret != LUA_OK) { const char *msg = lua_tostring(l, -1); Output("console.lua:\n%s\n", msg); c->AddOutput("Failed to run console.lua"); lua_pop(l, 1); } // pop capture_traceback function lua_pop(l, 1); LUA_DEBUG_END(l, 0); return 0; }
/** * Apply the environment to the function on the top of the stack. * * The environment will be initialized for the first time if needed. * * The function will remain on the stack afterwards. */ void Env::SetupEnv() { lua_State *state = GetState(); // fn - The compiled function. // env - The table that will be the environment for the function. // Initial stack: fn PushEnv(); // fn env // Apply the environment to the function. // Compiled Lua functions have one upvalue, which is the environment // it will execute in. lua_setupvalue(state, -2, 1); // fn }
void Script::Start() { // run on_start in gameobject's _ENV if (ObjectId == -1) { return; } lua_getglobal(vm, "objects"); lua_geti(vm, -1, ObjectId); lua_getfield(vm, -1, "on_start"); // push ms lua_pushvalue(vm, -2); lua_setupvalue(vm, -2, 1); int ret = lua_pcall(vm, 0, LUA_MULTRET, 0); if (ret) { printf("eror pcall: %s\n", lua_tostring(vm, -1)); } lua_pop(vm, 2); }
static inline void luaqueue_grown(lua_State* L,struct queue* q,int functab,int valuetbl){ uint64_t i; uint64_t newsz=q->size<<1; lua_createtable(L,newsz,0); setreadonly(L,-1); for(i=q->read;i<q->write;i++){ lua_rawgeti(L,valuetbl,(i&(q->size-1))+1); lua_rawseti(L,-2,(i&(newsz-1))+1); } lua_pushnil(L); while(lua_next(L,functab)){ lua_pushvalue(L,-3); lua_setupvalue(L,-2,2); lua_pop(L,1); } q->size=newsz; }
lua_scripts::script_info *lua_scripts::load_script(lua_State *L, char *filename) { if (int error = luaL_loadfile(L, filename)) { switch (error) { case LUA_ERRSYNTAX: gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: Syntax error in %s", filename); return nullptr; case LUA_ERRMEM: gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: Insufficent memory loading %s", filename); return nullptr; case LUA_ERRFILE: gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: Unable to load the file: %s", lua_tostring(L, -1)); hal.console->printf("Lua: File error: %s\n", lua_tostring(L, -1)); return nullptr; default: gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: Unknown error (%d) loading %s", error, filename); return nullptr; } } script_info *new_script = (script_info *)hal.util->heap_realloc(_heap, nullptr, sizeof(script_info)); if (new_script == nullptr) { // No memory, shouldn't happen, we even attempted to do a GC gcs().send_text(MAV_SEVERITY_CRITICAL, "Lua: Insufficent memory loading %s", filename); lua_pop(L, 1); // we can't use the function we just loaded, so ditch it return nullptr; } new_script->name = filename; new_script->next = nullptr; // find and create a sandbox for the new chunk lua_getglobal(L, "get_sandbox_env"); if (lua_pcall(L, 0, LUA_MULTRET, 0)) { gcs().send_text(MAV_SEVERITY_CRITICAL, "Scripting: Could not create sandbox: %s", lua_tostring(L, -1)); hal.console->printf("Lua: Scripting: Could not create sandbox: %s", lua_tostring(L, -1)); return nullptr; } load_generated_sandbox(L); lua_setupvalue(L, -2, 1); new_script->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX); // cache the reference new_script->next_run_ms = AP_HAL::millis64() - 1; // force the script to be stale return new_script; }
int luaT_setfenv52(lua_State *L, int iIndex) { int iType = lua_type(L, iIndex); switch(iType) { case LUA_TUSERDATA: lua_setuservalue(L, iIndex); return 1; case LUA_TFUNCTION: if(lua_iscfunction(L, iIndex)) { // Our convention: upvalue at #1 is environment if(lua_setupvalue(L, iIndex, 1) == nullptr) { lua_pop(L, 1); return 0; } return 1; } else { // Language convention: upvalue called _ENV is environment, which // might be shared with other functions. const char* sUpName = nullptr; for(int i = 1; (sUpName = lua_getupvalue(L, iIndex, i)) ; ++i) { lua_pop(L, 1); // lua_getupvalue puts the value on the stack, but we just want to replace it if(std::strcmp(sUpName, "_ENV") == 0) { luaL_loadstring(L, "local upv = ... return function() return upv end"); lua_insert(L, -2); lua_call(L, 1, 1); lua_upvaluejoin(L, iIndex, i, -1, 1); lua_pop(L, 1); return 1; } } lua_pop(L, 1); return 0; } default: return 0; } }
int Script::Update(int ms) { // run update in gameobject's _ENV if (ObjectId == -1) { return 1; } lua_getglobal(vm, "objects"); lua_geti(vm, -1, ObjectId); lua_getfield(vm, -1, "update"); // push ms lua_pushinteger(vm, ms); lua_pushvalue(vm, -3); lua_setupvalue(vm, -3, 1); int ret = lua_pcall(vm, 1, LUA_MULTRET, 0); if (ret) { printf("eror pcall: %s\n", lua_tostring(vm, -1)); } lua_pop(vm, 2); // printf("%d\n", lua_gettop(vm)); return 0; }
static void magnet_setfenv_mainfn(lua_State *L, int funcIndex) { /* (-1, 0, -) */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 /* set "_ENV" upvalue, which should be the first upvalue of a "main" lua * function if it uses any global names */ const char* first_upvalue_name = lua_getupvalue(L, funcIndex, 1); if (NULL == first_upvalue_name) return; /* doesn't have any upvalues */ lua_pop(L, 1); /* only need the name of the upvalue, not the value */ if (0 != strcmp(first_upvalue_name, "_ENV")) return; if (NULL == lua_setupvalue(L, funcIndex, 1)) { /* pop value if lua_setupvalue didn't set the (not existing) upvalue */ lua_pop(L, 1); } #else lua_setfenv(L, funcIndex); #endif }
static int luaB_load(lua_State *L) { int status; size_t l; int top = lua_gettop(L); const char *s = lua_tolstring(L, 1, &l); const char *mode = luaL_optstring(L, 3, "bt"); if(s != NULL) { /* loading a string? */ const char *chunkname = luaL_optstring(L, 2, s); status = luaL_loadbufferx(L, s, l, chunkname, mode); } else { /* loading from a reader function */ const char *chunkname = luaL_optstring(L, 2, "=(load)"); luaL_checktype(L, 1, LUA_TFUNCTION); lua_settop(L, RESERVEDSLOT); /* create reserved slot */ status = lua_load(L, generic_reader, NULL, chunkname, mode); } if(status == LUA_OK && top >= 4) { /* is there an 'env' argument */ lua_pushvalue(L, 4); /* environment for loaded function */ lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */ } return load_aux(L, status); }
static void Lcb_helper(void *ud, void *evtdata, ls_EventSignal *signal, ls_EventSlot *self) { lua_State *L = (lua_State*)ud; int top = lua_gettop(L); (void)signal; /* unused argument */ lsL_getregistry(L, LS_EVENT_CBOX); lua_rawgetp(L, -1, (void*)self); if (!lua_isnil(L, -1)) { if (evtdata != NULL) { lsL_getregistry(L, LS_EVENT_PBOX); lua_rawgetp(L, -1, evtdata); lua_setupvalue(L, -3, UV_UD); lua_call(L, 0, 0); } else { int i, args = lua_tointeger(L, top); for (i = 0; i < args; ++i) lua_pushvalue(L, top-args+i); lua_call(L, args, 0); } } lua_settop(L, top); }
//handle event int Script::HandleEvent(Event * Evt) { if (ObjectId == -1) { return 1; } // user event is larger than USER_EVENT if (Evt->EventId > USER_EVENT) { // this is event sent from scripts // get evnet table lua_getglobal(vm, "objects"); lua_geti(vm, -1, ObjectId); lua_getfield(vm, -1, "event"); // call callback within _ENV lua_geti(vm, -1, Evt->EventId); lua_pushvalue(vm, -3); lua_setupvalue(vm, -2, 1); int ret = lua_pcall(vm, 0, LUA_MULTRET, 0); if (ret) { printf("eror pcall: %s %d\n", lua_tostring(vm, -1), __LINE__); } // balance the stack lua_pop(vm, 3); } return 0; }
void LuaConsole::ExecOrContinue() { const std::string stmt = m_entryField->GetText(); int result; lua_State *L = Lua::manager->GetLuaState(); // If the statement is an expression, print its final value. result = luaL_loadbuffer(L, ("return " + stmt).c_str(), stmt.size()+7, CONSOLE_CHUNK_NAME); if (result == LUA_ERRSYNTAX) result = luaL_loadbuffer(L, stmt.c_str(), stmt.size(), CONSOLE_CHUNK_NAME); // check for an incomplete statement // (follows logic from the official Lua interpreter lua.c:incomplete()) if (result == LUA_ERRSYNTAX) { const char eofstring[] = "<eof>"; size_t msglen; const char *msg = lua_tolstring(L, -1, &msglen); if (msglen >= (sizeof(eofstring) - 1)) { const char *tail = msg + msglen - (sizeof(eofstring) - 1); if (strcmp(tail, eofstring) == 0) { // statement is incomplete -- allow the user to continue on the next line m_entryField->SetText(stmt + "\n"); m_entryField->ResizeRequest(); ResizeRequest(); lua_pop(L, 1); return; } } } if (result == LUA_ERRSYNTAX) { size_t msglen; const char *msg = lua_tolstring(L, -1, &msglen); AddOutput(std::string(msg, msglen)); lua_pop(L, 1); return; } if (result == LUA_ERRMEM) { // this will probably fail too, since we've apparently // just had a memory allocation failure... AddOutput("memory allocation failure"); return; } // set the global table lua_getfield(L, LUA_REGISTRYINDEX, "ConsoleGlobal"); lua_setupvalue(L, -2, 1); std::istringstream stmt_stream(stmt); std::string string_buffer; std::getline(stmt_stream, string_buffer); AddOutput("> " + string_buffer); while(!stmt_stream.eof()) { std::getline(stmt_stream, string_buffer); AddOutput(" " + string_buffer); } // perform a protected call int top = lua_gettop(L) - 1; // -1 for the chunk itself result = lua_pcall(L, 0, LUA_MULTRET, 0); if (result == LUA_ERRRUN) { size_t len; const char *s = lua_tolstring(L, -1, &len); AddOutput(std::string(s, len)); } else if (result == LUA_ERRERR) { size_t len; const char *s = lua_tolstring(L, -1, &len); AddOutput("error in error handler: " + std::string(s, len)); } else if (result == LUA_ERRMEM) { AddOutput("memory allocation failure"); } else { int nresults = lua_gettop(L) - top; if (nresults) { std::ostringstream ss; // call tostring() on each value and display it lua_getglobal(L, "tostring"); // i starts at 1 because Lua stack uses 1-based indexing for (int i = 1; i <= nresults; ++i) { ss.str(std::string()); if (nresults > 1) ss << "[" << i << "] "; // duplicate the tostring function for the call lua_pushvalue(L, -1); lua_pushvalue(L, top+i); result = lua_pcall(L, 1, 1, 0); size_t len = 0; const char *s = 0; if (result == 0) s = lua_tolstring(L, -1, &len); ss << s ? std::string(s, len) : "<internal error when converting result to string>"; // pop the result lua_pop(L, 1); AddOutput(ss.str()); } } } // pop all return values lua_settop(L, top); // update the history list if (! result) { // command succeeded... add it to the history unless it's just // an exact repeat of the immediate last command if (m_statementHistory.empty() || (stmt != m_statementHistory.back())) m_statementHistory.push_back(stmt); // clear the entry box m_entryField->SetText(""); ResizeRequest(); } // always forget the history position and clear the stashed command m_historyPosition = -1; m_stashedStatement.clear(); }
LUAMOD_API int luaopen_profile(lua_State *L) { luaL_checkversion(L); luaL_Reg l[] = { { "start", lstart }, { "stop", lstop }, { "resume", lresume }, { "yield", lyield }, { "resume_co", lresume_co }, { "yield_co", lyield_co }, { NULL, NULL }, }; luaL_newlibtable(L,l); lua_newtable(L); // table thread->start time lua_newtable(L); // table thread->total time lua_newtable(L); // weak table lua_pushliteral(L, "kv"); lua_setfield(L, -2, "__mode"); lua_pushvalue(L, -1); lua_setmetatable(L, -3); lua_setmetatable(L, -3); lua_pushnil(L); // cfunction (coroutine.resume or coroutine.yield) luaL_setfuncs(L,l,3); int libtable = lua_gettop(L); lua_getglobal(L, "coroutine"); lua_getfield(L, -1, "resume"); lua_CFunction co_resume = lua_tocfunction(L, -1); if (co_resume == NULL) return luaL_error(L, "Can't get coroutine.resume"); lua_pop(L,1); lua_getfield(L, libtable, "resume"); lua_pushcfunction(L, co_resume); lua_setupvalue(L, -2, 3); lua_pop(L,1); lua_getfield(L, libtable, "resume_co"); lua_pushcfunction(L, co_resume); lua_setupvalue(L, -2, 3); lua_pop(L,1); lua_getfield(L, -1, "yield"); lua_CFunction co_yield = lua_tocfunction(L, -1); if (co_yield == NULL) return luaL_error(L, "Can't get coroutine.yield"); lua_pop(L,1); lua_getfield(L, libtable, "yield"); lua_pushcfunction(L, co_yield); lua_setupvalue(L, -2, 3); lua_pop(L,1); lua_getfield(L, libtable, "yield_co"); lua_pushcfunction(L, co_yield); lua_setupvalue(L, -2, 3); lua_pop(L,1); lua_settop(L, libtable); return 1; }
bool CMLuaScript::Load() { status = Failed; if (luaL_loadfile(L, T2Utf(filePath))) { Log(lua_tostring(L, -1)); return false; } lua_createtable(L, 0, 2); lua_pushvalue(L, -1); lua_setfield(L, -2, "_G"); lua_pushlightuserdata(L, this); lua_setfield(L, -2, "Script"); lua_createtable(L, 0, 2); lua_getglobal(L, "_G"); lua_setfield(L, -2, "__index"); lua_setmetatable(L, -2); lua_setupvalue(L, -2, 1); if (luaM_pcall(L, 0, 1)) return false; status = Loaded; if (lua_isnoneornil(L, -1)) return true; luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, -1, moduleName); if (!lua_toboolean(L, -1)) { lua_pop(L, 1); lua_pushvalue(L, -2); lua_setfield(L, -2, moduleName); lua_pop(L, 1); } else lua_remove(L, -2); if (!lua_istable(L, -1)) return true; lua_getfield(L, -1, "Load"); if (lua_isfunction(L, -1)) luaM_pcall(L); else lua_pop(L, 1); lua_getfield(L, -1, "Unload"); if (lua_isfunction(L, -1)) { lua_pushvalue(L, -1); unloadRef = luaL_ref(L, LUA_REGISTRYINDEX); } lua_pop(L, 1); lua_pop(L, 1); return true; }
static void unpack_value (lua_State *L, const char *buf, size_t len, const char **p, int *idx) { size_t l; char val_type = **p; mar_incr_ptr(MAR_CHR); switch (val_type) { case LUA_TBOOLEAN: lua_pushboolean(L, *(char*)*p); mar_incr_ptr(MAR_CHR); break; case LUA_TNUMBER: lua_pushnumber(L, *(lua_Number*)*p); mar_incr_ptr(MAR_I64); break; case LUA_TSTRING: mar_next_len(l, uint32_t); lua_pushlstring(L, *p, l); mar_incr_ptr(l); break; case LUA_TTABLE: { char tag = *(char*)*p; mar_incr_ptr(MAR_CHR); if (tag == MAR_TREF) { int ref; mar_next_len(ref, int); lua_rawgeti(L, 2, ref); } else if (tag == MAR_TVAL) { mar_next_len(l, uint32_t); lua_newtable(L); lua_pushvalue(L, -1); lua_rawseti(L, 2, (*idx)++); mar_unpack(L, *p, l, idx); mar_incr_ptr(l); } else if (tag == MAR_TUSR) { mar_next_len(l, uint32_t); lua_newtable(L); mar_unpack(L, *p, l, idx); lua_rawgeti(L, -1, 1); lua_call(L, 0, 1); lua_remove(L, -2); lua_pushvalue(L, -1); lua_rawseti(L, 2, (*idx)++); mar_incr_ptr(l); } else { luaL_error(L, "bad encoded data"); } break; } case LUA_TFUNCTION: { size_t nups; int i; mar_Buffer dec_buf; char tag = *(char*)*p; mar_incr_ptr(1); if (tag == MAR_TREF) { int ref; mar_next_len(ref, int); lua_rawgeti(L, 2, ref); } else { mar_next_len(l, uint32_t); dec_buf.data = (char*)*p; dec_buf.size = l; dec_buf.head = l; dec_buf.seek = 0; lua_load(L, (lua_Reader)buf_read, &dec_buf, "=marshal"); mar_incr_ptr(l); lua_pushvalue(L, -1); lua_rawseti(L, 2, (*idx)++); mar_next_len(l, uint32_t); lua_newtable(L); mar_unpack(L, *p, l, idx); nups = lua_objlen(L, -1); for (i=1; i <= nups; i++) { lua_rawgeti(L, -1, i); lua_setupvalue(L, -3, i); } lua_pop(L, 1); mar_incr_ptr(l); } break; } case LUA_TUSERDATA: { char tag = *(char*)*p; mar_incr_ptr(MAR_CHR); if (tag == MAR_TREF) { int ref; mar_next_len(ref, int); lua_rawgeti(L, 2, ref); } else if (tag == MAR_TUSR) { mar_next_len(l, uint32_t); lua_newtable(L); mar_unpack(L, *p, l, idx); lua_rawgeti(L, -1, 1); lua_call(L, 0, 1); lua_remove(L, -2); lua_pushvalue(L, -1); lua_rawseti(L, 2, (*idx)++); mar_incr_ptr(l); } else { /* tag == MAR_TVAL */ lua_pushnil(L); } break; } case LUA_TTHREAD: lua_pushnil(L); break; default: luaL_error(L, "bad code"); } }
const char * LuaDebug::SetUpvalue(int funcindex, int n) const { return lua_setupvalue(L(), funcindex, n); }
static void mar_decode_value (lua_State *L, const char *buf, size_t len, const char **p, size_t *idx) { size_t l; char val_type = **p; mar_incr_ptr(MAR_CHR); switch (val_type) { case LUA_TBOOLEAN: lua_pushboolean(L, *(char*)*p); mar_incr_ptr(MAR_CHR); break; case LUA_TNUMBER: lua_pushnumber(L, *(lua_Number*)*p); mar_incr_ptr(MAR_I64); break; case LUA_TLIGHTUSERDATA: { void * ptr=(void*)*(void**)*p; lua_pushlightuserdata(L, ptr); mar_incr_ptr(MAR_I64); } break; case LUA_TSTRING: mar_next_len(l, uint32_t); lua_pushlstring(L, *p, l); mar_incr_ptr(l); break; case LUA_TTABLE: { char tag = *(char*)*p; mar_incr_ptr(MAR_CHR); if (tag == MAR_TREF) { int ref; mar_next_len(ref, int); lua_rawgeti(L, SEEN_IDX, ref); } else if (tag == MAR_TVAL) { mar_next_len(l, uint32_t); lua_newtable(L); lua_pushvalue(L, -1); lua_rawseti(L, SEEN_IDX, (*idx)++); mar_decode_table(L, *p, l, idx); mar_incr_ptr(l); } else if (tag == MAR_TUSR) { mar_next_len(l, uint32_t); lua_newtable(L); mar_decode_table(L, *p, l, idx); lua_rawgeti(L, -1, 1); lua_call(L, 0, 1); lua_remove(L, -2); lua_pushvalue(L, -1); lua_rawseti(L, SEEN_IDX, (*idx)++); mar_incr_ptr(l); } else { luaL_error(L, "bad encoded data"); } break; } case LUA_TFUNCTION: { size_t nups; int i; mar_Buffer dec_buf; char tag = *(char*)*p; mar_incr_ptr(1); if (tag == MAR_TREF) { int ref; mar_next_len(ref, int); lua_rawgeti(L, SEEN_IDX, ref); } else { mar_next_len(l, uint32_t); dec_buf.data = (char*)*p; dec_buf.size = l; dec_buf.head = l; dec_buf.seek = 0; lua_load(L, (lua_Reader)buf_read, &dec_buf, "=marshal" #if LUA_VERSION_NUM > 501 ,NULL #endif ); mar_incr_ptr(l); lua_pushvalue(L, -1); lua_rawseti(L, SEEN_IDX, (*idx)++); mar_next_len(l, uint32_t); lua_newtable(L); mar_decode_table(L, *p, l, idx); nups = lua_objlen(L, -1); for (i=1; i <= nups; i++) { lua_rawgeti(L, -1, i); #if LUA_VERSION_NUM > 501 if(lua_type(L,-1)==LUA_TSTRING) { size_t len=0; const char * s=lua_tolstring(L,-1,&len); if(!strncmp(s,LEDA_ENV_MARKER,sizeof(LEDA_ENV_MARKER))) { lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); lua_remove(L,-2); } } #endif lua_setupvalue(L, -3, i); } lua_pop(L, 1); mar_incr_ptr(l); } break; } case LUA_TUSERDATA: { char tag = *(char*)*p; mar_incr_ptr(MAR_CHR); if (tag == MAR_TREF) { int ref; mar_next_len(ref, int); lua_rawgeti(L, SEEN_IDX, ref); } else if (tag == MAR_TUSR) { mar_next_len(l, uint32_t); lua_newtable(L); mar_decode_table(L, *p, l, idx); lua_rawgeti(L, -1, 1); lua_call(L, 0, 1); lua_remove(L, -2); lua_pushvalue(L, -1); lua_rawseti(L, SEEN_IDX, (*idx)++); mar_incr_ptr(l); } else { /* tag == MAR_TVAL */ lua_pushnil(L); } break; } case LUA_TNIL: case LUA_TTHREAD: lua_pushnil(L); break; default: luaL_error(L, "bad code"); } }
static inline int _cloneNoTable(lua_State *L, const int idx, lua_State *L_, const int r_lv ) { int ret_= 1; switch(lua_type(L, idx ) ) { case LUA_TSTRING: { size_t l; const char *s= lua_tolstring(L, idx, &l ); lua_pushlstring(L_, s, l ); } break; case LUA_TNUMBER: lua_pushnumber(L_, lua_tonumber(L, idx ) ); break; case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(L_, lua_touserdata(L, idx ) ); break; case LUA_TBOOLEAN: lua_pushboolean(L_, lua_toboolean(L, idx ) ); break; case LUA_TUSERDATA: { // userdata 的 meta 暂时不能拷贝 const size_t l= lua_objlen(L, idx ); memmove(lua_newuserdata(L_, l ), lua_touserdata(L, idx ), l ); if(0) //屏蔽 meta 处理 if(lua_getmetatable(L, idx ) ) { const int k= _cloneRecursion(L, lua_gettop(L ), L_, ((0<= r_lv )? r_lv: -1 ) ); lua_pop(L, 1 ); if((0<= r_lv )&& lua_istable(L_, -1 )&& (0< k ) ) printf("%*.s__{%3d}\n", (r_lv- 1 )* 2, "", k ); lua_setmetatable(L_, -2 ); } } break; case LUA_TFUNCTION: if(lua_iscfunction(L, idx ) ) { int j= 1; lua_CFunction f= lua_tocfunction(L, idx ); for(j= 1; UPVALUE_MAX>= j; ++j ) { //设置函数的 upvalue if(!lua_getupvalue(L, idx, j ) ) break; _cloneRecursion(L, lua_gettop(L ), L_, ((0<= r_lv )? (r_lv+ 1 ): -1 ) ); lua_pop(L, 1 ); } lua_pushcclosure(L_, f, j- 1 ); } else { int j= 1; DUMP_CB ud; memset(&ud, 0, sizeof(ud ) ); lua_pushvalue(L, idx ); lua_dump(L, writer_CB, &ud ); if(ud.p ) { //载入函数到新的栈 lua_load(L_, reader_CB, &ud, (char * )0 ); free(ud.p ); } lua_pop(L, 1 ); for(j= 1; UPVALUE_MAX>= j; ++j ) { //设置函数的 upvalue if(!lua_getupvalue(L, idx, j ) ) break; printf("upvalue %d\n", j ); _cloneRecursion(L, lua_gettop(L ), L_, ((0<= r_lv )? (r_lv+ 1 ): -1 ) ); lua_pop(L, 1 ); lua_setupvalue(L_, -2, j ); } } break; case LUA_TNIL: lua_pushnil(L_ ); break; case LUA_TNONE: case LUA_TTHREAD: //? default: ret_= 0; break; } return ret_; }