static void getlocal (void) { lua_Object func = lua_stackedfunction(luaL_check_int(1)); lua_Object val; char *name; if (func == LUA_NOOBJECT) /* level out of range? */ return; /* return nil */ else if (lua_getparam(2) != LUA_NOOBJECT) { /* 2nd argument? */ if ((val = lua_getlocal(func, findlocal(func, 2), &name)) != LUA_NOOBJECT) { lua_pushobject(val); lua_pushstring(name); } /* else return nil */ } else { /* collect all locals in a table */ lua_Object result = lua_createtable(); int i; for (i=1; ;i++) { if ((val = lua_getlocal(func, i, &name)) == LUA_NOOBJECT) break; lua_pushobject(result); lua_pushstring(name); lua_pushobject(val); lua_settable(); /* result[name] = value */ } lua_pushobject(result); } }
static int db_getlocal (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; const char *name; int nvar = luaL_checkint(L, arg+2); /* local-variable index */ if (lua_isfunction(L, arg + 1)) { /* function argument? */ lua_pushvalue(L, arg + 1); /* push function */ lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ return 1; } else { /* stack-level argument */ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); name = lua_getlocal(L1, &ar, nvar); if (name) { lua_xmove(L1, L, 1); /* push local value */ lua_pushstring(L, name); /* push name */ lua_pushvalue(L, -2); /* re-order */ return 2; } else { lua_pushnil(L); /* no name (nor value) */ return 1; } } }
static bool dump_local(struct luadebug_debugger *session, const char *option) { int i; const char *local; const int index = option ? atoi(option) : -1; if (index < 0) { session->user->print(session->user, "Locals\n"); for (i=1; (local = lua_getlocal(session->L, &session->frame, i)); ++i) { session->user->print(session->user, " #%d\t%s = ", i, local); pprint(session->L, session->user, -1, false, NULL); lua_pop(session->L, 1); } } else { local = lua_getlocal(session->L, &session->frame, index); if (!local) { session->user->print(session->user, RED "invalid local index '%d'\n" CLEAR, index); } else { session->user->print(session->user, " #%d\t%s = ", index, local); pprint(session->L, session->user, -1, true, NULL); lua_pop(session->L, 1); } } return false; }
int wxLuaDebugData::EnumerateStackEntry(lua_State* L, int stack_frame, wxArrayInt& references) { wxCHECK_MSG(L, 0, wxT("Invalid lua_State")); wxCHECK_MSG(M_DEBUGREFDATA != NULL, 0, wxT("Invalid ref data")); lua_Debug luaDebug = INIT_LUA_DEBUG; int count = 0; if (lua_getstack(L, stack_frame, &luaDebug) != 0) { int stack_idx = 1; wxString name(lua2wx(lua_getlocal(L, &luaDebug, stack_idx))); while (!name.IsEmpty()) { //wxPrintf(wxT("%s lua_getlocal :%s\n"), lua_Debug_to_wxString(luaDebug).c_str(), name.c_str()); int wxl_valuetype = WXLUA_TNONE; wxString value; wxString source(lua2wx(luaDebug.source)); int lua_value_type = GetTypeValue(L, -1, &wxl_valuetype, value); int val_flag_type = 0; int val_ref = LUA_NOREF; if (lua_value_type == LUA_TTABLE) { val_ref = RefTable(L, -1, &val_flag_type, WXLUA_DEBUGITEM_VALUE_REF, references); } else if (lua_value_type == LUA_TUSERDATA) { if (lua_getmetatable(L, -1)) // doesn't push anything if nil { val_ref = RefTable(L, -1, &val_flag_type, WXLUA_DEBUGITEM_VALUE_REF, references); lua_pop(L, 1); } } Add(new wxLuaDebugItem(name, WXLUA_TNONE, value, wxl_valuetype, source, val_ref, 0, val_flag_type)); ++count; lua_pop(L, 1); // remove variable value name = lua2wx(lua_getlocal(L, &luaDebug, ++stack_idx)); } } return count; }
void set_lua_variable(lua_State *l, char *name, int value) { /* See if there's a local variable that matches the given name. * If we find it, then set the value. If not, we'll keep walking back * up the stack levels until we've exhausted all of the closures. * At that point, set a global instead. */ lua_Debug ar; int stacksize = get_call_stack_size(l); int stacklevel,i; /* This C call is stacklevel 0; the function that called is, 1; and so on. */ for (stacklevel=0; stacklevel<stacksize; stacklevel++) { const char *local_name; lua_getstack(l, stacklevel, &ar); lua_getinfo(l, "nSluf", &ar); /* get all the info there is. Could probably be whittled down. */ i=1; while ( (local_name=lua_getlocal(l, &ar, i++)) ) { if (!strcmp(name, local_name)) { /* Found the local! Set it, and exit. */ lua_pop(l, 1); // pop the local's old value lua_pushinteger(l, value); // push the new value lua_setlocal(l, &ar, i-1); // set the value (note: i was incremented) lua_pop(l, 2); return; } lua_pop(l, 1); } } /* Didn't find a local with that name anywhere. Set it as a global. */ lua_pushinteger(l, value); lua_setglobal(l, name); lua_pop(l, 3); }
/* error function */ int lf_errorfunc(lua_State *L) { int depth = 0; int frameskip = 1; lua_Debug frame; if(session.report_color) printf("\033[01;31m%s\033[00m\n", lua_tostring(L,-1)); else printf("%s\n", lua_tostring(L,-1)); if(session.lua_backtrace) { printf("backtrace:\n"); while(lua_getstack(L, depth, &frame) == 1) { depth++; lua_getinfo(L, "nlSf", &frame); /* check for functions that just report errors. these frames just confuses more then they help */ if(frameskip && strcmp(frame.short_src, "[C]") == 0 && frame.currentline == -1) continue; frameskip = 0; /* print stack frame */ printf(" %s(%d): %s %s\n", frame.short_src, frame.currentline, frame.name, frame.namewhat); /* print all local variables for the frame */ if(session.lua_locals) { int i; const char *name = 0; i = 1; while((name = lua_getlocal(L, &frame, i)) != NULL) { printf(" %s = ", name); debug_print_lua_value(L,-1); printf("\n"); lua_pop(L,1); i++; } i = 1; while((name = lua_getupvalue(L, -1, i)) != NULL) { printf(" upvalue #%d: %s ", i-1, name); debug_print_lua_value(L, -1); lua_pop(L,1); i++; } } } } return 1; }
//***************************************************************************** int LuaBindings::GetLocals(LuaStack stack) { DebugContext * pDebugContext = GetContextIfPaused(stack); if (pDebugContext != NULL) { int frame = lua_tointeger(stack, 2); lua_Debug debug; LuaDebug pFrameDebug = pDebugContext->GetDebug(); if (frame > 0) { pFrameDebug = &debug; lua_getstack(pDebugContext->pStack, frame, pFrameDebug); } lua_pushinteger(stack, 0); lua_newtable(stack); // and get all the locals now!!! for (int i = 1, nitems = 0;;i++) { const char *varname = lua_getlocal(pDebugContext->pStack, pFrameDebug, i); if (varname == NULL) break ; // pop the variable value off - we do not return this (or // should we?) lua_pop(pDebugContext->pStack, 1); // ignore temporaries? // if (strncmp("(*", varname, 2) != 0) { // push the new variable index lua_pushinteger(stack, ++nitems); // push a table to hold the variable info lua_newtable(stack); // push the index and the variable name lua_pushinteger(stack, i); lua_setfield(stack, -2, "index"); lua_pushstring(stack, varname); lua_setfield(stack, -2, "name"); lua_settable(stack, -3); } } } return 2; }
// ----------------------------------------------------------------------- // Retrieve a global or local variable int Read_Ref_Argument(lua_State *L, int idx, lua_Debug *local, int NewString) { char *Variable_Name = (char *) luaL_checkstring(L, idx); char *local_name; int i; int j; Read_Again: memset(local, 0, sizeof(lua_Debug)); // See if it's a local variable i = 0; while(lua_getstack(L, i, local)) { j = 1; while(local_name = (char *) lua_getlocal(L, local, j)) { if(strcmp(Variable_Name, local_name) == 0) { // This is the variable return(-j); } // Nope, remove it from the stack lua_pop(L, 1); j++; } i++; } // See if it's a global one lua_getfield(L, LUA_GLOBALSINDEX, Variable_Name); local->name = Variable_Name; if(lua_isnil(L, -1)) { // Didn't find it: create it as a global variable. lua_pop(L, 1); if(NewString) { lua_pushstring(L, ""); lua_setglobal(L, Variable_Name); } else { lua_pushnumber(L, 0); lua_setglobal(L, Variable_Name); } goto Read_Again; } else { return(idx); } }
static void mark_thread(lua_State *L, lua_State *dL, const void * parent, const char *desc) { const void * t = readobject(L, dL, parent, desc); if (t == NULL) return; int level = 0; lua_State *cL = lua_tothread(L,-1); if (cL == L) { level = 1; } else { // mark stack int top = lua_gettop(cL); luaL_checkstack(cL, 1, NULL); int i; char tmp[16]; for (i=0;i<top;i++) { lua_pushvalue(cL, i+1); sprintf(tmp, "[%d]", i+1); mark_object(cL, dL, cL, tmp); } } lua_Debug ar; luaL_Buffer b; luaL_buffinit(dL, &b); while (lua_getstack(cL, level, &ar)) { char tmp[128]; lua_getinfo(cL, "Sl", &ar); luaL_addstring(&b, ar.short_src); if (ar.currentline >=0) { char tmp[16]; sprintf(tmp,":%d ",ar.currentline); luaL_addstring(&b, tmp); } int i,j; for (j=1;j>-1;j-=2) { for (i=j;;i+=j) { const char * name = lua_getlocal(cL, &ar, i); if (name == NULL) break; snprintf(tmp, sizeof(tmp), "%s : %s:%d",name,ar.short_src,ar.currentline); mark_object(cL, dL, t, tmp); } } ++level; } luaL_addstring(&b, "thread: "); luaL_pushresult(&b); lua_rawsetp(dL, SOURCE, t); lua_pop(L,1); }
static int search_local_var(lua_State *state, lua_Debug *ar, const char* var) { int i; const char *name; for(i = 1; (name = lua_getlocal(state, ar, i)) != NULL; i++) { if(strcmp(var,name) == 0) { return i; } // not match, pop out the var's value lua_pop(state, 1); } return 0; }
int find_locals(lua_State *L, lua_Debug *ar, const char *var_name) { int index = 1; const char *name; while((name = lua_getlocal(L, ar, index)) != NULL) { if(strcmp(name, var_name) == 0) { return index; } if(strcmp(name, "(*temporary)") == 0) { lua_pop(L, 1); break; } index++; lua_pop(L, 1); } return 0; }
static int getlocal (lua_State *L) { lua_Debug ar; const char *name; if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ return luaL_argerror(L, 1, "level out of range"); name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); if (name) { lua_pushstring(L, name); lua_pushvalue(L, -2); return 2; } else { lua_pushnil(L); return 1; } }
bool VRSDClientLuaImplementation::GetLocalType(const char* pVariableName, char * pUserDataTypeName) { VASSERT(m_pLuaState); if(!m_pLuaState || !m_pActivationRecord) return false; // we can only get local symbols without a crash if we are really in a Lua code execution path if(strcmp(m_pActivationRecord->what, "Lua")) return true; VLuaStackCleaner stackCleaner(m_pLuaState); ScopedBooleanToTrue disableDebugHook(m_bDebuggerRetrievingValues); const char* pSymbolName = NULL; int iLocalIndex = 1; VMemoryTempBuffer<512> copyBuffer(pVariableName); // operate on a copy string in the tokenizer VStringTokenizerInPlace Tokenizer(copyBuffer.AsChar(), '.'); char* pCurrent = Tokenizer.Next(); pUserDataTypeName[0] = 0; while((pSymbolName = lua_getlocal(m_pLuaState, m_pActivationRecord, iLocalIndex)) != NULL) { //stack: ..., localX, TOP // check if this local variable is the one we want if(!strcmp(pSymbolName, pCurrent)) { // there is already the local on the stack if(LookupPath(Tokenizer) != HKV_SUCCESS) return false; const char * szName = VSWIG_Lua_typename(m_pLuaState, -1); sprintf(pUserDataTypeName, "%s", szName); return pUserDataTypeName[0] != 0; } // clean up the stack and increment the index to get the next local variable lua_pop(m_pLuaState, 1); //stack: ..., TOP iLocalIndex++; } return false; }
bool VRSDClientLuaImplementation::GetUserDataPointerFromLocal(const char* szVariable, void** ppUserData, void ** ppEnvironment) { VASSERT(m_pLuaState); if(!m_pLuaState || !m_pActivationRecord) return false; // we can only get local symbols without a crash if we are really in a Lua code execution path if(strcmp(m_pActivationRecord->what, "Lua")) return true; ScopedBooleanToTrue disableDebugHook(m_bDebuggerRetrievingValues); VLuaStackCleaner stackCleaner(m_pLuaState); char* pSymbolName = NULL; int iLocalIndex = 1; VMemoryTempBuffer<512> copyBuffer(szVariable); // operate on a copy string in the tokenizer VStringTokenizerInPlace Tokenizer(copyBuffer.AsChar(), '.'); char* pCurrent = Tokenizer.Next(); while((pSymbolName = (char*)lua_getlocal(m_pLuaState, m_pActivationRecord, iLocalIndex)) != NULL) { //Stack: ..., localX, TOP // check if this local variable is the one we want if(!strcmp(pSymbolName, pCurrent)) { VLuaStackCleaner innerStackCleaner(m_pLuaState); //there is already the local on the stack... if(LookupPath(Tokenizer) != HKV_SUCCESS) return false; // now the variable is at the top of the stack *ppUserData = lua_touserdata(m_pLuaState, -1); //Stack: ..., localX, {field}, TOP *ppEnvironment = m_pLuaState; return true; } // remove the value and update the index to get the next local variable lua_pop(m_pLuaState, 1); iLocalIndex++; } return false; }
void CDbgLuaHelper::DrawLocalVariables() { debugger()->ClearLocalVariables(); int nLevel = debugger()->GetStackTraceLevel(); lua_Debug ar; if ( lua_getstack (L, nLevel, &ar) ) { int i = 1; const char *name; while ((name = lua_getlocal(L, &ar, i++)) != NULL) { DrawVariable(L,name,true); lua_pop(L, 1); /* remove variable value */ } } }
bool CDbgLuaHelper::GetCalltip(const char *szWord, char *szCalltip) { int nLevel = debugger()->GetStackTraceLevel(); lua_Debug ar; if ( lua_getstack (L, nLevel, &ar) ) { int i = 1; const char *name; while ((name = lua_getlocal(L, &ar, i++)) != NULL) { if ( xr_strcmp(name, szWord)==0 ) { char szRet[64]; Describe(szRet, -1); sprintf(szCalltip, "local %s : %s ", name, szRet); lua_pop(L, 1); /* remove variable value */ return true; } lua_pop(L, 1); /* remove variable value */ } } lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushnil(L); /* first key */ while (lua_next(L, -2)) { const char* name = lua_tostring(L, -2); if ( xr_strcmp(name, szWord)==0 ) { char szRet[64]; Describe(szRet, -1); sprintf(szCalltip, "global %s : %s ", name, szRet); lua_pop(L, 3); /* remove table, key, value */ return true; } lua_pop(L, 1); // pop value, keep key for next iteration; } lua_pop(L, 1); // pop table of globals; return false; }
static int findlocal (lua_Object func, int arg) { lua_Object v = lua_getparam(arg); if (lua_isnumber(v)) return (int)lua_getnumber(v); else { char *name = luaL_check_string(arg); int i = 0; int result = -1; char *vname; while (lua_getlocal(func, ++i, &vname) != LUA_NOOBJECT) { if (strcmp(name, vname) == 0) result = i; /* keep looping to get the last var with this name */ } if (result == -1) luaL_verror("no local variable `%.50s' at given level", name); return result; } }
bool VRSDClientLuaImplementation::IsLocalUserDataOfType(const char* Name, const char* Type) { VASSERT(m_pLuaState); if(!m_pLuaState || !m_pActivationRecord) return false; // we can only get local symbols without a crash if we are really in a Lua code execution path if(strcmp(m_pActivationRecord->what, "Lua")) return true; VLuaStackCleaner stackCleaner(m_pLuaState); ScopedBooleanToTrue disableDebugHook(m_bDebuggerRetrievingValues); const char* pSymbolName = NULL; int iLocalIndex = 1; VMemoryTempBuffer<512> copyBuffer(Name); // operate on a copy string in the tokenizer VStringTokenizerInPlace Tokenizer(copyBuffer.AsChar(), '.'); char* pCurrent = Tokenizer.Next(); while((pSymbolName = lua_getlocal(m_pLuaState, m_pActivationRecord, iLocalIndex)) != NULL) { //stack: ..., localX, TOP // check if this local variable is the one we want if(!strcmp(pSymbolName, pCurrent)) { VLuaStackCleaner innerStackCleaner(m_pLuaState); // there is already the local on the stack if(LookupPath(Tokenizer) != HKV_SUCCESS) return false; // now the variable is at the top of the stack return LUA_TestUserData(m_pLuaState, -1, Type) != NULL; } // increment the index to get the next local variable iLocalIndex++; lua_pop(m_pLuaState, 1); } return false; }
static int db_getlocal (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; const char *name; if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); if (name) { lua_xmove(L1, L, 1); lua_pushstring(L, name); lua_pushvalue(L, -2); return 2; } else { lua_pushnil(L); return 1; } }
LuaObject LuaState::GetLocalByName( int level, const char* name ) { lua_State * L = GetCState(); lua_Debug ar; int i; const char *localName; if (lua_getstack(L, level, &ar) == 0) return LuaObject(this); /* failure: no such level in the stack */ i = 1; while ((localName = lua_getlocal(L, &ar, i++)) != NULL) { if (strcmp(name, localName) == 0) { LuaObject obj(this, -1); lua_pop(L, 1); return obj; } lua_pop(L, 1); /* remove variable value */ } return LuaObject(this); }
//***************************************************************************** int LuaBindings::GetLocal(LuaStack stack) { DebugContext * pDebugContext = GetContextIfPaused(stack); if (pDebugContext != NULL) { int lvindex = lua_tointeger(stack, 2); int nlevels = lua_tointeger(stack, 3); int frame = lua_tointeger(stack, 4); lua_Debug debug; LuaDebug pFrameDebug = pDebugContext->GetDebug(); if (frame > 0) { pFrameDebug = &debug; lua_getstack(pDebugContext->pStack, frame, pFrameDebug); } const char *varname = lua_getlocal(pDebugContext->pStack, pFrameDebug, lvindex); if (varname == NULL) { lua_pushinteger(stack, -1); lua_pushstring(stack, "Invalid variable index."); } else { // output code - 0 => success lua_pushinteger(stack, 0); // local variable value LuaUtils::TransferValueToStack(pDebugContext->pStack, stack, -1, nlevels, varname); // pop the value of the local variable // of the stack being debugged!! lua_pop(pDebugContext->pStack, 1); } } return 2; }
int capture_env(struct lua_State *L, int frame) { int i; const char *local; lua_Debug ar; LUA_STACK_MARK(L); if (!lua_getstack(L, frame, &ar)) { return -1; } lua_getinfo(L, "f", &ar); lua_newtable(L); for (i=1; (local = lua_getlocal(L, &ar, i)); ++i) { lua_setfield(L, -2, local); } for (i=1; (local = lua_getupvalue(L, -2, i)); ++i) { lua_setfield(L, -2, local); } lua_newtable(L); lua_getfenv(L, -3); lua_setfield(L, -2, "__index"); lua_getfenv(L, -3); lua_setfield(L, -2, "__newindex"); lua_setmetatable(L, -2); lua_remove(L, -2); LUA_STACK_CHECK(L, 1); return lua_gettop(L); }
void CDbgLuaHelper::CoverGlobals() { lua_newtable(L); // save there globals covered by locals int nLevel = debugger()->GetStackTraceLevel(); lua_Debug ar; if ( lua_getstack (L, nLevel, &ar) ) { int i = 1; const char *name; while ((name = lua_getlocal(L, &ar, i++)) != NULL) { /* SAVE lvalue */ lua_pushstring(L, name); /* SAVE lvalue name */ lua_pushvalue(L, -1); /* SAVE lvalue name name */ lua_pushvalue(L, -1); /* SAVE lvalue name name name */ lua_insert(L, -4); /* SAVE name lvalue name name */ lua_rawget(L, LUA_GLOBALSINDEX); /* SAVE name lvalue name gvalue */ lua_rawset(L, -5); // save global value in local table /* SAVE name lvalue */ lua_rawset(L, LUA_GLOBALSINDEX); /* SAVE */ } } }
bool VRSDClientLuaImplementation::UpdateLocalVariable(const char* Variable, const char* NewValue) { if(!Variable || !NewValue) return false; VASSERT(m_pLuaState); if(!m_pLuaState || !m_pActivationRecord) return false; // we can only get local symbols without a crash if we are really in a Lua code execution path if(strcmp(m_pActivationRecord->what, "Lua")) return true; VLuaStackCleaner stackCleaner(m_pLuaState); ScopedBooleanToTrue disableDebugHook(m_bDebuggerRetrievingValues); const char* pSymbolName = NULL; int iLocalIndex = 1; VMemoryTempBuffer<512> copyBuffer(Variable); // operate on a copy string in the tokenizer VStringTokenizerInPlace Tokenizer(copyBuffer.AsChar(), '.'); char* pCurrent = Tokenizer.Next(); int i = 0; const char* pLastField = NULL; // go through all local variables while((pSymbolName = lua_getlocal(m_pLuaState, m_pActivationRecord, iLocalIndex)) != NULL) { // check if this local variable is the one we want if(!strcmp(pSymbolName, pCurrent)) { VLuaStackCleaner innerStackCleaner(m_pLuaState); if(LookupPath(Tokenizer, &pLastField) != HKV_SUCCESS) return false; // now the variable is at the top of the stack, update its value int iLuaType = lua_type(m_pLuaState, -1); // pop off the field again lua_pop(m_pLuaState, 1); bool bIsIntegerKey = false; if(pLastField && VStringUtil::IsIntegerString(pLastField)) { bIsIntegerKey = true; lua_pushnumber(m_pLuaState, (LUA_NUMBER)atoi(pLastField)); } if (!PushValue(iLuaType, NewValue)) { return false; } if(Tokenizer.GetTokenCount() > 1) { VASSERT(pLastField != NULL); if(bIsIntegerKey) { lua_settable(m_pLuaState, -3); } else { lua_setfield(m_pLuaState, -2, pLastField); } } else { lua_setlocal(m_pLuaState, m_pActivationRecord, iLocalIndex); } break; } // clean up the stack and increment the index to get the next local variable lua_pop(m_pLuaState, 1); iLocalIndex++; } return true; }
bool wxLuaDebugTarget::EvaluateExpr(int exprRef, const wxString &strExpr) // FIXME - check this code { wxString strResult(wxT("Error")); int nReference = LUA_NOREF; EnterLuaCriticalSection(); { lua_State* L = m_wxlState.GetLuaState(); if (wxStrpbrk(strExpr.c_str(), wxT(" ~=<>+-*/%(){}[]:;,.\"'")) != NULL) { // an expression int nOldTop = lua_gettop(L); wxLuaCharBuffer charbuf(strExpr); int nResult = luaL_loadbuffer(L, charbuf.GetData(), charbuf.Length(), "debug"); if (nResult == 0) nResult = lua_pcall(L, 0, LUA_MULTRET, 0); // call main if (nResult != 0) wxlua_pushwxString(L, wxlua_LUA_ERR_msg(nResult)); else if (lua_gettop(L) == nOldTop) lua_pushliteral(L, "OK"); nReference = m_wxlState.wxluaR_Ref(-1, &wxlua_lreg_refs_key); lua_settop(L, nOldTop); // throw out all return values } else { lua_Debug ar = INIT_LUA_DEBUG; int iLevel = 0; bool fFound = false; while (lua_getstack(L, iLevel++, &ar) != 0) { int iIndex = 0; wxString name = lua2wx(lua_getlocal(L, &ar, ++iIndex)); if (!name.IsEmpty()) { if (strExpr == name) { nReference = m_wxlState.wxluaR_Ref(-1, &wxlua_lreg_refs_key); fFound = true; break; } lua_pop(L, 1); } if (fFound) break; name = lua2wx(lua_getlocal(L, &ar, ++iIndex)); } if (!fFound) { int nOldTop = lua_gettop(L); lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushnil(L); while (lua_next(L, -2) != 0) { if (lua_type(L, -2) == LUA_TSTRING) { wxString name = lua2wx(lua_tostring(L, -2)); if (strExpr == name) { nReference = m_wxlState.wxluaR_Ref(-1, &wxlua_lreg_refs_key); // reference value lua_pop(L, 2); // pop key and value fFound = true; break; } } lua_pop(L, 1); // removes 'value'; } lua_settop(L, nOldTop); // the table of globals. } } if (m_wxlState.wxluaR_GetRef(nReference, &wxlua_lreg_refs_key)) { m_wxlState.wxluaR_Unref(nReference, &wxlua_lreg_refs_key); int wxl_type = 0; wxString value; wxLuaDebugData::GetTypeValue(L, -1, &wxl_type, value); strResult.Printf(wxT("%s : %s"), wxluaT_typename(L, wxl_type).c_str(), value.c_str()); lua_pop(L, 1); } } LeaveLuaCriticalSection(); return NotifyEvaluateExpr(exprRef, strResult); }
const char * LuaDebug::GetLocal(const lua_Debug * ar, int n) const { return lua_getlocal(L(), ar, n); }
/*** check whether the calling function's argument have the expected types. `checks( [level], t_1, ..., t_n)` causes an error if the type of argument #`i` in stack frame #`level` isn't as described by `t_i`, for i in `[1...n]`. `level` is optional, it defaults to one (checks the function immediately calling `checks`). @function [parent=#global] checks @param level the number of stack levels to ignore in the error message, should it be produced. Optional, defaults to 1. @param varargs one type string per expected argument. @return nothing on success, throw an error on failure. */ static int checks( lua_State *L) { lua_Debug ar; int level=1, i=1, r; if( lua_isnumber( L, 1)) { i = 2; level = lua_tointeger( L, 1); } r = lua_getstack( L, level, & ar); if( ! r) luaL_error( L, "checks() must be called within a Lua function"); /* loop for each checked argument in stack frame. */ for( /* i already initialized. */; ! lua_isnoneornil( L, i); i++) { const char *expectedType = luaL_checkstring( L, i); // - lua_getlocal( L, & ar, i); // val (value whose type is checked) /* 1. Check for nil if type is optional. */ if( '?' == expectedType[0]) { if( ! expectedType[1] /* expectedType == "?". */ || lua_isnoneornil( L, -1)) { /* actualType == "nil". */ lua_pop( L, 1); continue; // - } expectedType++; } const char *actualType = lua_typename( L, lua_type( L, -1)); /* 1'. if the template is "!", check for non-nilness. */ if( '!' == expectedType[0] && '\0' == expectedType[1]) { if( lua_isnoneornil( L, -1)) { // val==nil return error( L, level, i, "non-nil", actualType); } else { // val~=nil lua_pop( L, 1); continue; // - } } /* 2. Check real type. */ if( matches( actualType, expectedType)) { lua_pop( L, 1); continue; // - } /* 3. Check for type name in metatable. */ if( lua_getmetatable( L, -1)) { // val, mt lua_getfield( L, -1, "__type"); // val, mt, __type? if( lua_isstring( L, -1)) { // val, mt, __type if( matches( luaL_checkstring( L, -1), expectedType)) { lua_pop( L, 3); continue; // - } else { /* non-matching __type field. */ lua_pop( L, 2); // val } } else { /* no __type field. */ lua_pop( L, 2); // val } } else { /* no metatable. */ } // val /* 4. Check for a custom typechecking function. */ lua_getfield( L, LUA_REGISTRYINDEX, "checkers"); // val, checkers const char *p = expectedType; while( 1) { const char *q = strchr( p, '|'); if( ! q) q = p + strlen( p); lua_pushlstring( L, p, q-p); // val, checkers, expType lua_gettable( L, -2); // val, checkers, checkers.expType? if( lua_isfunction( L, -1)) { lua_pushvalue( L, -3); // val, checkers, checkers.expType, val r = lua_pcall( L, 1, 1, 0); // val, checkers, result || msg if( ! r && lua_toboolean( L, -1)) {// val, checkers, result==true lua_pop( L, 3); // - break; } else { // val, checkers, errormsg lua_pop( L, 1); // val, checkers } } else { /* no such custom checker */ // val, checkers, nil lua_pop( L, 1); // val, checkers } if( ! *q) { /* last possible expected type. */ lua_pop( L, 2); return error( L, level, i, expectedType, actualType); } else { p = q+1; } } /* for each expected type */ } /* for each i */ return 0; }
bool VRSDClientLuaImplementation::GetSubSymbolsForLocal(char* LocalName, DynArray_cl<VRSDScriptSymbol>& SubSymbols, unsigned int& SubSymbolCount) { VASSERT(m_pLuaState); if(!m_pLuaState || !m_pActivationRecord) return false; SubSymbolCount = 0; // we can only get local symbols without a crash if we are really in a Lua code execution path if(strcmp(m_pActivationRecord->what, "Lua")) return true; VLuaStackCleaner stackCleaner(m_pLuaState); ScopedBooleanToTrue disableDebugCallback(m_bDebuggerRetrievingValues); char* pSymbolName = NULL; int iLocalIndex = 1; VMemoryTempBuffer<512> copyBuffer(LocalName); // operate on a copy string in the tokenizer VStringTokenizerInPlace Tokenizer(copyBuffer.AsChar(), '.'); char* pCurrent = Tokenizer.Next(); while((pSymbolName = (char*)lua_getlocal(m_pLuaState, m_pActivationRecord, iLocalIndex)) != NULL) { //stack: .., localX, TOP // check if this local variable is the one we want if(!strcmp(pSymbolName, pCurrent)) { //the local is already on the stack if(LookupPath(Tokenizer) != HKV_SUCCESS) return false; // now we can iterate over the contents of the table // first key for the iteration lua_pushnil(m_pLuaState); //stack: .., localX, {field}, nil, TOP //access the last field while (lua_next(m_pLuaState, -2) != 0) //stack: .., localX, {field}, key, value TOP { // we only want string fields and numeric fields // (lua_isstring returns also true for numbers, using // tostring later on will cast the number to a string) int iKeyType = lua_type(m_pLuaState, -2); if (iKeyType==LUA_TNUMBER || iKeyType==LUA_TSTRING) { VString sKeyBuffer; //this if prevents a conversion of number on the Lua stack if(iKeyType==LUA_TNUMBER) sKeyBuffer.Format("%1.0f", lua_tonumber(m_pLuaState, -2)); else sKeyBuffer = lua_tostring(m_pLuaState, -2); if(!sKeyBuffer.IsEmpty()) { int iValueType = lua_type(m_pLuaState, -1); VString sValueBuffer; // table member variable switch (iValueType) { case LUA_TTABLE: // add a symbol for the table AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), "table", VRSDScriptSymbol::SYMBOL_TABLE); break; case LUA_TNUMBER: // numeric member variable sValueBuffer.Format("%f", lua_tonumber(m_pLuaState, -1)); AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), sValueBuffer.AsChar(), VRSDScriptSymbol::SYMBOL_NUMBER); break; case LUA_TSTRING: AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), lua_tostring(m_pLuaState, -1), VRSDScriptSymbol::SYMBOL_STRING); break; case LUA_TFUNCTION: sValueBuffer.Format("function:0x%p", lua_tocfunction(m_pLuaState, -1)); AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), sValueBuffer.AsChar(), VRSDScriptSymbol::SYMBOL_FUNCTION); break; case LUA_TBOOLEAN: AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), lua_toboolean(m_pLuaState, -1) ? "true" : "false", VRSDScriptSymbol::SYMBOL_BOOLEAN); break; case LUA_TNIL: AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), "nil", VRSDScriptSymbol::SYMBOL_CLASS); break; case LUA_TTHREAD: sValueBuffer.Format("thread:0x%p", lua_tothread(m_pLuaState, -1)); AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), sValueBuffer.AsChar(), VRSDScriptSymbol::SYMBOL_CLASS); break; case LUA_TUSERDATA: sValueBuffer.Format("userdata:0x%p", lua_touserdata(m_pLuaState, -1)); AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), sValueBuffer.AsChar(), VRSDScriptSymbol::SYMBOL_USERDATA); break; default: AddSymbol(SubSymbols, SubSymbolCount, sKeyBuffer.AsChar(), "unknown", VRSDScriptSymbol::SYMBOL_STRING); break; } } } // remove the value, keep the key for the next iteration lua_pop(m_pLuaState, 1); //stack: .., localX, {field}, key, TOP } return true; } // clean up the stack and increment the index to get the next local variable lua_pop(m_pLuaState, 1); //stack: .., TOP iLocalIndex++; } return true; }
bool VRSDClientLuaImplementation::GetLocalSymbols(DynArray_cl<VRSDScriptSymbol>& LocalSymbols, unsigned int& LocalSymbolCount) { VASSERT(m_pLuaState); if(!m_pLuaState || !m_pActivationRecord) return false; LocalSymbolCount = 0; // we can only get local symbols without a crash if we are really in a Lua code execution path if(strcmp(m_pActivationRecord->what, "Lua")) return true; const char* pSymbolName = NULL; int iLocalIndex = 1; while((pSymbolName = lua_getlocal(m_pLuaState, m_pActivationRecord, iLocalIndex)) != NULL) { // skip lua internal temporary variables (they start with an '(') if(pSymbolName[0] != '(') { // if the variable is a table, get all child variables (one level deep only) if(lua_istable(m_pLuaState, -1)) { // add a symbol for the table AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, "table", VRSDScriptSymbol::SYMBOL_TABLE); } // numeric member variable else if(lua_type(m_pLuaState, -1) == LUA_TNUMBER) { char buffer[32]; sprintf(buffer, "%f", lua_tonumber(m_pLuaState, -1)); AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, buffer, VRSDScriptSymbol::SYMBOL_NUMBER); } // string member variable else if(lua_type(m_pLuaState, -1) == LUA_TSTRING) { AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, lua_tostring(m_pLuaState, -1), VRSDScriptSymbol::SYMBOL_STRING); } else if(lua_isfunction(m_pLuaState, -1)) { AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, "function", VRSDScriptSymbol::SYMBOL_FUNCTION); } else if(lua_isuserdata(m_pLuaState, -1)) { char buffer[128]; swig_type_info* type = (swig_type_info *)LUA_GetSwigType(m_pLuaState, -1); void * pUserData = lua_touserdata(m_pLuaState, -1); if(type) { vis_snprintf(buffer, 128, "userdata:0x%p [%s: 0x%p]", pUserData, type->str, ((swig_lua_userdata*)pUserData)->ptr); } else { vis_snprintf(buffer, 128, "userdata:0x%p", lua_touserdata(m_pLuaState, -1)); } AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, buffer, VRSDScriptSymbol::SYMBOL_USERDATA); } else if(lua_isboolean(m_pLuaState, -1)) { int iBoolVal = lua_toboolean(m_pLuaState, -1); AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, iBoolVal ? "true" : "false", VRSDScriptSymbol::SYMBOL_BOOLEAN); } else if(lua_isnil(m_pLuaState, -1)) { AddSymbol(LocalSymbols, LocalSymbolCount, pSymbolName, "nil", VRSDScriptSymbol::SYMBOL_CLASS); } } // clean up the stack and increment the index to get the next local variable lua_pop(m_pLuaState, 1); iLocalIndex++; } return true; }
//----------------------------------------------------------------// void MOAIHarness::ReceiveVariableGet(lua_State *L, json_t* node) { // Get the keys to traverse to the target variable json_t* np_keys = json_object_get(node, "Keys"); if (np_keys == NULL || json_typeof(np_keys) != JSON_ARRAY) return; // Check to see if we were actually provided keys size_t keyCount = json_array_size(np_keys); if (keyCount == 0) return; // Get the root key name (which has to be a string) json_t* np_root_key = json_array_get(np_keys, 0); if (json_typeof(np_root_key) != JSON_STRING) return; std::string root(json_string_value(np_root_key)); // Get the stack level to look for loval variables at json_t* np_stack_level = json_object_get(node, "Level"); if (np_stack_level == NULL || json_typeof(np_stack_level) != JSON_INTEGER) return; json_int_t level = json_integer_value(np_stack_level); // Check for the root name in the local namespace bool found = false; lua_Debug ar; if (lua_getstack(L, (int)level, &ar)) { // Look for a local variable match const char* localName; for (int local = 1; (localName = lua_getlocal(L, &ar, local)) != 0; ++local) { if (root == localName) { found = true; break; } lua_pop(L, 1); } if (!found) { // Push the function onto the stack lua_getinfo(L, "f", &ar); // Look for an upvalue match const char* upvalueName; for (int upvalue = 1; (upvalueName = lua_getupvalue(L, -1, upvalue)) != 0; ++upvalue) { if (root == upvalueName) { found = true; break; } lua_pop(L, 1); } // Pop the function off the stack lua_remove(L, found ? -2 : -1); } } // Check for the root name in the global namespace if (!found) { lua_getglobal(L, root.c_str()); } // Traverse through our child keys for (size_t childIndex = 1; !lua_isnil(L, -1) && childIndex < keyCount; ++childIndex) { json_t* np_key = json_array_get(np_keys, childIndex); bool valid = true; // First check for complex type keys if (json_typeof(np_key) == JSON_OBJECT) { // Check for the correct datapair encoding for keys json_t* anticonflict = json_object_get(np_key, JSON_DATAPAIR_ANTICONFLICT_KEY); json_t* np_type = json_object_get(np_key, JSON_DATAPAIR_NAME_KEY); json_t* np_data = json_object_get(np_key, JSON_DATAPAIR_DATA_KEY); bool isDatapair = anticonflict && json_typeof(anticonflict) == JSON_STRING && strcmp(json_string_value(anticonflict), JSON_DATAPAIR_ANTICONFLICT_VALUE) == 0 && np_type && json_typeof(np_type) == JSON_STRING && np_data && json_typeof(np_data) == JSON_INTEGER; if (isDatapair && lua_istable(L, -1)) { // Iterate through the keys of the table, looking for complex // types with the same type and address const char* keyType = json_string_value(np_type); json_int_t keyPtr = json_integer_value(np_data); bool keyFound = false; lua_pushnil(L); while (lua_next(L, -2) != 0) { // If this key is a complex type, compare its // type and address if (const void* ptr = lua_topointer(L, -2)) { int type = lua_type(L, -2); if ((int)ptr == (int)keyPtr && strcmp(keyType, lua_typename(L, type)) == 0) { // Pop the table and key off the stack, leaving the value lua_remove(L, -2); lua_remove(L, -2); keyFound = true; break; } } lua_pop(L, 1); } if (keyFound) { continue; } } valid = false; } // Push the key onto the stack switch (json_typeof(np_key)) { case JSON_STRING: lua_pushstring(L, json_string_value(np_key)); break; case JSON_INTEGER: lua_pushinteger(L, (lua_Integer)json_integer_value(np_key)); break; case JSON_REAL: lua_pushnumber(L, (lua_Number)json_real_value(np_key)); break; case JSON_TRUE: case JSON_FALSE: lua_pushboolean(L, json_typeof(np_key) == JSON_TRUE); break; default: valid = false; break; } // If we don't have a valid key, just pop the table off the // stack and return a nil value if (!valid) { lua_pop(L, 1); lua_pushnil(L); } // Otherwise, call a function to get the table value else { lua_pushcfunction(L, MOAIHarness::VariableGetCallback); lua_insert(L, -3); // If an error occurred getting the value, just push nil if (lua_pcall(L, 2, 1, 0)) { lua_pushnil(L); } } } // Convert the result to a json object json_t* result = MOAIHarness::ConvertStackIndexToJSON(L, -1, true); lua_pop(L, 1); // Return the result to the caller SendVariableGetResult(np_keys, result); json_decref(result); }