// When running under the debugger, this will freeze the execution state // allowing us to inspect it. Otherwise we get a fatal error and exit static int loomAssert(lua_State *L) { bool fail = false; if (lua_isnil(L, 1)) { fail = true; } if (lua_isnumber(L, 1)) { if (!lua_tonumber(L, 1)) { fail = true; } } if (lua_isstring(L, 1)) { if (!strlen(lua_tostring(L, 1))) { fail = true; } } if (lua_isboolean(L, 1)) { if (!lua_toboolean(L, 1)) { fail = true; } } if (fail) { if (!debuggerRunning) { lua_pushfstring(L, "Loom Assertion Failed: %s", lua_tostring(L, 2)); lua_error(L); } else { // trip debugger assertion = true; getCallStack(L, ASSERT_EVENT); if (!lua_isnil(L, -1)) { assertEventDelegate.incArgCount(); assertEventDelegate.invoke(); } } } return 0; }
int NativeDelegate::__op_assignment(lua_State *L) { NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1, true, "system.NativeDelegate"); if (!delegate) { LSError("Unable to get native delegate on += operator"); } // set the VM, and recreate callbacks table delegate->setVM(L, true); delegate->getCallbacks(L); if (!lua_istable(L, -1)) { LSError("Bad native delegates table"); } // clear current callbacks for (int i = 0; i < delegate->_callbackCount; i++) { lua_pushnumber(L, (double)i); lua_pushnil(L); lua_settable(L, -3); } // reset delegate->_callbackCount = 0; if (lua_isnil(L, 2)) { return 0; } if (!lua_isfunction(L, 2) && !lua_iscfunction(L, 2)) { LSError("Unknown type on NativeDelegate assignment operator"); } // add the lua function or cfunction to our delegate's callback table lua_pushnumber(L, (double)0); lua_pushvalue(L, 2); lua_settable(L, -3); lua_pop(L, 1); // pop __lscallbacks delegate->_callbackCount++; return 0; }
int NativeDelegate::__op_plusassignment(lua_State *L) { NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1, "system.NativeDelegate"); if (!delegate) { LSError("Unable to get native delegate on += operator"); } delegate->setVM(L); delegate->getCallbacks(L); int tidx = lua_gettop(L); if (!lua_istable(L, -1)) { LSError("Bad native delegates table"); } if (lua_isfunction(L, 2) || lua_iscfunction(L, 2)) { // check if we already added this callback for (int i = 0; i < delegate->_callbackCount; i++) { lua_rawgeti(L, tidx, i); if (lua_equal(L, 2, -1)) { lua_pop(L, 1); return 0; // already added } lua_pop(L, 1); } // add the lua function or cfunction to our delegate's callback table lua_pushnumber(L, (double)delegate->_callbackCount++); lua_pushvalue(L, 2); lua_settable(L, -3); lua_pop(L, 1); // pop __lscallbacks } else { LSError("Unknown type on NativeDelegate += operator"); } return 0; }
bool NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate) { Mutex::Locker locker (m_delegates_mutex); if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ()) return false; m_delegates.push_back (&native_delegate); native_delegate.InitializeDelegate (this); return true; }
bool NativeProcessProtocol::RegisterNativeDelegate( NativeDelegate &native_delegate) { std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); if (std::find(m_delegates.begin(), m_delegates.end(), &native_delegate) != m_delegates.end()) return false; m_delegates.push_back(&native_delegate); native_delegate.InitializeDelegate(this); return true; }
void NativeDelegate::invalidateLuaStateDelegates(lua_State *L) { utArray<NativeDelegate *> *delegates = NULL; if (sActiveNativeDelegates.find(L) != UT_NPOS) { delegates = *(sActiveNativeDelegates.get(L)); } if (delegates) { for (UTsize i = 0; i < delegates->size(); i++) { NativeDelegate *delegate = delegates->at(i); delegate->invalidate(); } sActiveNativeDelegates.erase(L); delete delegates; } }
int NativeDelegate::__op_minusassignment(lua_State *L) { NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1, "system.NativeDelegate"); if (!delegate) { LSError("Unable to get native delegate on += operator"); } if (!delegate->_callbackCount) { return 0; } delegate->setVM(L); delegate->getCallbacks(L); int tidx = lua_gettop(L); if (!lua_istable(L, tidx)) { LSError("Bad native delegates table"); } if (lua_isfunction(L, 2) || lua_iscfunction(L, 2)) { int idx = -1; for (int i = 0; i < delegate->_callbackCount; i++) { lua_rawgeti(L, tidx, i); if (lua_equal(L, 2, -1)) { idx = i; lua_pop(L, 1); break; } lua_pop(L, 1); } // this function was never added in the first place if (idx == -1) { return 0; } // shift the other delegates down lua_pushnumber(L, (double)idx); lua_pushnil(L); lua_settable(L, tidx); int ntable = 0; if (delegate->_callbackCount > 1) { // temp table lua_newtable(L); ntable = lua_gettop(L); int c = 0; for (int nidx = 0; nidx < delegate->_callbackCount; nidx++) { lua_pushnumber(L, (double)nidx); lua_gettable(L, tidx); if (lua_isnil(L, -1)) { lua_pop(L, 1); continue; } lua_pushnumber(L, (double)c); lua_pushvalue(L, -2); lua_settable(L, ntable); // pop lua_function lua_pop(L, 1); c++; } } // clear it delegate->_callbackCount--; // and copy from new temp table for (int nidx = 0; nidx < delegate->_callbackCount; nidx++) { lua_pushnumber(L, (double)nidx); lua_pushnumber(L, (double)nidx); lua_gettable(L, ntable); lua_settable(L, tidx); } } else { LSError("Unknown type on NativeDelegate -= operator"); } return 0; }
// Main lua VM debug hook static void debugHook(lua_State *L, lua_Debug *ar) { int top = lua_gettop(L); // line event if ((ar->event == LUA_HOOKLINE) && lineEventDelegate.getCount() && !assertion) { // If we're finishing an method we are not interested // in line events until we have returned from the method if (finishMethod) { return; } // if we're not stepping, have no breakpoints, and haven't hit a Debug.debug() // we are not interested in the line event if (!stepping && !breakpoints.size() && !debugBreak) { return; } // get the call stack at this line getCallStack(L, LINE_EVENT); // if we don't have a valid stack, return if (lua_isnil(L, -1)) { lua_pop(L, 1); return; } // call the native delegate lineEventDelegate.incArgCount(); lineEventDelegate.invoke(); } // return hook if ((ar->event == LUA_HOOKRET) && returnEventDelegate.getCount() && !assertion) { // if we don't have a method we're finishing, we // don't care if (!finishMethod) { return; } // get the call stack getCallStack(L, RETURN_EVENT); // invalid stack? No problem, bail if (lua_isnil(L, -1)) { lua_pop(L, 1); return; } // call the debugger's native delegate returnEventDelegate.incArgCount(); returnEventDelegate.invoke(); } // call hook if ((ar->event == LUA_HOOKCALL) && callEventDelegate.getCount() && !assertion) { // we on;y care about call events when stepping over if (!blocking || !stepping || !stepOver) { return; } // get the call stack for this event getCallStack(L, CALL_EVENT); // invalid? If so, bail if (lua_isnil(L, -1)) { lua_pop(L, 1); return; } // call the debugger's event delegate callEventDelegate.incArgCount(); callEventDelegate.invoke(); } lua_settop(L, top); }