From: John L. <jr...@us...> - 2005-12-22 18:42:50
|
Update of /cvsroot/wxlua/wxLua/modules/wxlua/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19516/wxLua/modules/wxlua/src Modified Files: internal.cpp wxlbind.cpp wxlintrp.cpp wxlstate.cpp Log Message: Removed the wxLuaInterpreter - all functions transferred to the wxLuaState wxLuaInterpreter is typedefed to wxLuaState temporarily Index: internal.cpp =================================================================== RCS file: /cvsroot/wxlua/wxLua/modules/wxlua/src/internal.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** internal.cpp 12 Dec 2005 05:16:31 -0000 1.21 --- internal.cpp 22 Dec 2005 18:42:35 -0000 1.22 *************** *** 46,51 **** //#endif - extern wxLuaInterpreter *wxFindLuaInterpreter(lua_State *L); - extern int s_wxluatag_wxBitmap; extern int s_wxluatag_wxEvtHandler; --- 46,49 ---- *************** *** 1243,1255 **** } - #if 1 // defined(LUA_EMBEDDED) // FIXME - who gets the error message? - #define LUAERROR_OUTPUT(msg) \ - wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); \ - luaInterpreter->DisplayError(msg); - #else - #define LUAERROR_OUTPUT(msg) \ - wxLuaHandler::GetHandler().DisplayError(msg); - #endif - int LUACALL LuaError(lua_State *L, int status, int top) { --- 1241,1244 ---- *************** *** 1276,1280 **** errorMsg += wxT("\n"); ! LUAERROR_OUTPUT(errorMsg) lua_settop(L, top); status = 0; --- 1265,1271 ---- errorMsg += wxT("\n"); ! wxLuaState wxlState(L); ! if (wxlState.Ok()) ! wxlState.DisplayError(errorMsg); lua_settop(L, top); status = 0; Index: wxlstate.cpp =================================================================== RCS file: /cvsroot/wxlua/wxLua/modules/wxlua/src/wxlstate.cpp,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** wxlstate.cpp 16 Dec 2005 05:12:26 -0000 1.14 --- wxlstate.cpp 22 Dec 2005 18:42:35 -0000 1.15 *************** *** 56,62 **** --- 56,343 ---- // ---------------------------------------------------------------------------- + // WXLUA_THREAD_INTERCEPTION - make sure that coroutines lua_State's are tracked + // ---------------------------------------------------------------------------- + + // add lua_States created from lua's coroutines + #define WXLUA_THREAD_INTERCEPTION + + extern "C" + { + #include "lua/include/lua.h" + #include "lua/include/lauxlib.h" + #include "lua/include/lualib.h" + + #ifdef WXLUA_THREAD_INTERCEPTION + // See lua/src/lstate.c for added hook into luaE_newthread() + #include "lua/include/luathread.h" + #endif //WXLUA_THREAD_INTERCEPTION + } + + #ifdef WXLUA_THREAD_INTERCEPTION + + // Hook into function calls to luaE_newthread (calls from coroutine.create/wrap) + // and add the new lua_State as a child sharing it's wxLuaStateVariables + void wxLuaState_newthread_handler(lua_State *L, lua_State *L1) + { + // L is the original lua_State, L1 new child thread + wxLuaState wxlState(L); + wxCHECK_RET(wxlState.Ok(), wxT("Invalid wxLuaState")); + + // put into the hashmap + wxLuaStateRefData::s_wxHashMapLuaStateRefData[L1] = wxlState.GetLuaStateRefData(); + + // Stick us into the lua_State - push key, value + lua_pushstring( L1, "__wxLuaStateRefData" ); + lua_pushlightuserdata( L1, (void*)wxlState.GetRefData() ); + // set the value + lua_settable( L1, LUA_REGISTRYINDEX ); + } + + // Hook into function calls to luaE_freethread (calls from coroutine.create/wrap) + // and remove the child lua_State + void wxLuaState_freethread_handler(lua_State *WXUNUSED(L), lua_State *L1) + { + // L is the original lua_State, L1 child thread, don't remove L + //wxPrintf(wxT("wxLuaInterpreter_freethread_handler lua_State from a thread L=%ld L1=%ld\n"), (long)L, (long)L1); fflush(stdout); + wxLuaStateRefData::s_wxHashMapLuaStateRefData.erase(L1); + } + + static void wxLuaState_SetupThreadHandlers() + { + if (luaX_getnewthreadhandler() == NULL) + luaX_setnewthreadhandler( wxLuaState_newthread_handler ); + if (luaX_getfreethreadhandler() == NULL) + luaX_setfreethreadhandler( wxLuaState_freethread_handler ); + } + + #endif //WXLUA_THREAD_INTERCEPTION + + // ---------------------------------------------------------------------------- // C functions for lua used in wxLuaState // ---------------------------------------------------------------------------- + + int LuaPrint( lua_State *L ) + { + wxString msg; + int i, n = lua_gettop(L); + + // figure out the types here in c++ land + lua_getglobal(L, "tostring"); + for (i = 1; i <= n; i++) + { + if (i > 1) msg.Append(wxT(", ")); + + if (lua_isstring(L, i)) + msg += lua2wx(lua_tostring(L, i)); + else if (lua_isnumber(L, i)) + msg += wxString::Format(wxT("%lf"), lua_tonumber(L, i)); + else if (lua_iscfunction(L, i)) + msg += wxString::Format(wxT("C function %ld"), (long int)lua_tocfunction(L, i)); + else if (lua_isuserdata(L, i)) + msg += wxString::Format(wxT("User data %ld"), (long int)lua_touserdata(L, i)); + else if (lua_isboolean(L, i)) + msg += lua_toboolean(L,i) ? wxT("true") : wxT("false"); + else if (lua_isnil(L,i)) + msg += wxT("nil"); + else if (lua_isnone(L,i)) + msg += wxT("unknown"); + else + msg += wxString::Format(wxT("%s:%p"), lua_typename(L,lua_type(L,i)), lua_topointer(L,i)); + } + + if (!msg.IsEmpty()) + { + wxLuaState wxlState(L); + + if (wxlState.Ok()) + { + wxLuaEvent event(wxEVT_LUA_CONSOLE, wxlState.GetId(), wxlState); + event.SetString(msg); + wxlState.SendEvent( event ); + } + } + + return 0; // no items put onto stack + } + + // copied from the Lua 5.0.1 debug library + #define LEVELS1 12 /* size of the first part of the stack */ + #define LEVELS2 10 /* size of the second part of the stack */ + + // copied from the Lua 5.0.1 debug library + int LuaTraceback(lua_State *L) + { + int level = 1; // skip level 0 (it's this function) + int firstpart = 1; // still before eventual `...' + lua_Debug ar; + if (lua_gettop(L) == 0) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, 1)) // no string message + return 1; + else + lua_pushliteral(L, "\n"); + + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L, level++, &ar)) + { + if (level > LEVELS1 && firstpart) + { + // no more than `LEVELS2' more levels? + if (!lua_getstack(L, level+LEVELS2, &ar)) + level--; // keep going + else + { + lua_pushliteral(L, "\n\t..."); // too many levels + while (lua_getstack(L, level+LEVELS2, &ar)) // find last levels + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + switch (*ar.namewhat) + { + case 'g': // global + case 'l': // local + case 'f': // field + case 'm': // method + lua_pushfstring(L, " in function `%s'", ar.name); + break; + default: { + if (*ar.what == 'm') // main? + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); // C function or tail call + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + } + lua_concat(L, lua_gettop(L)); + } + lua_concat(L, lua_gettop(L)); + return 1; + } + + int LuaAlert( lua_State *L ) + { + wxLuaState wxlState(L); + + if (wxlState.Ok()) + { + wxString msg = lua2wx(lua_tostring(L, 1)); + + wxLuaEvent event(wxEVT_LUA_ERROR, wxlState.GetId(), wxlState); + event.SetString(msg); + + long line = -1; + wxString lineStr = msg; + + // Why can't I fill a lua_Debug here? Try to get the line number + // by parsing the error message that looks like this, 1 is linenumber + // [string "a = 1("]:1: unexpected symbol near `<eof>' + while(!lineStr.IsEmpty()) + { + lineStr = lineStr.AfterFirst(wxT(']')); + if ((lineStr.Length() > 0) && (lineStr.GetChar(0) == wxT(':'))) + { + lineStr = lineStr.AfterFirst(wxT(':')); + if (lineStr.IsEmpty() || lineStr.BeforeFirst(wxT(':')).ToLong(&line)) + break; + } + } + + event.SetInt((int)line); + wxlState.SendEvent( event ); + } + + return 0; + } + + void LuaDebugHook(lua_State *L, lua_Debug *LDebug) + { + wxLuaState wxlState(L); + + // during program shutdown this can be called - ignore it + if (!wxlState.Ok()) + return; + + // FIXME - for select event types we don't want to do anything + wxEventType evtType = wxlState.GetInEventType(); + if ((evtType != wxEVT_NULL)) + //(evtType == wxEVT_IDLE) && (evtType == wxEVT_PAINT) && + //(evtType == wxEVT_DESTROY) && (evtType == wxEVT_CLOSE_WINDOW)) + return; + + // they want to break the program, restore old debug hook, then error out + if (wxlState.GetDebugHookBreak()) + { + // restore hook to previous state see wxLuaInterpreter::Break() + wxlState.SetLuaDebugHook(wxlState.GetLuaDebugHookCount(), + wxlState.GetLuaDebugHookYield(), + wxlState.GetLuaDebugHookSendEvt(), + wxlState.GetLuaDebugHook()); + + terror(L, wx2lua(wxlState.GetDebugHookBreakMessage())); + return; + } + + if (wxlState.GetLuaDebugHookSendEvt()) + { + int ret = 0; + ret = lua_getinfo(L, "l", LDebug); // line (ldebug.currentline) + + wxLuaEvent event(wxEVT_LUA_DEBUG_HOOK, wxlState.GetId(), wxlState); + event.m_lua_Debug = LDebug; + event.SetInt(LDebug->currentline); + wxlState.SendEvent( event ); + if (event.m_stop_interpreter) + terror(L, "Interpreter stopped"); + } + + // Try to yield *after* sending event to allow C++ gui update + if (wxlState.GetLuaDebugHookYield() > 0) + { + // yield based on number of ms passed NOT every hook event + unsigned long last_time = wxlState.GetLastLuaDebugHookTime(); + unsigned long cur_time = wxGetLocalTimeMillis().GetLo(); + + if ((cur_time > last_time + wxlState.GetLuaDebugHookYield()) || + (cur_time < last_time)) // wrapped + { + wxlState.SetLastLuaDebugHookTime( cur_time ); + + bool painting = false; + + #if WXWIN_COMPATIBILITY_24 || !wxCHECK_VERSION(2, 5, 0) + wxNode* node; + #else + wxHashTable::Node* node; + #endif + + // FIXME - wxGTK crashes if wxYield[IfNeeded] is called within a paint handler? I think + wxlState.GetLuaStateRefData()->m_pTrackedList->BeginFind(); + node = wxlState.GetLuaStateRefData()->m_pTrackedList->Next(); + while (node) + { + if (wxDynamicCast(node->GetData(), wxPaintDC)) + { + painting = true; + break; + } + node = wxlState.GetLuaStateRefData()->m_pTrackedList->Next(); + } + + if (!painting) + wxYieldIfNeeded(); + } + } + } + // A function object needs to be deleted because the object is being // garbage collected. *************** *** 231,234 **** --- 512,528 ---- m_pTrackedList = new wxHashTable(wxKEY_INTEGER); + m_is_running = false; + m_debug_hook_break = false; + m_debug_hook_break_msg = wxT("Break"); + + m_last_debug_hook_time = wxGetLocalTimeMillis().GetLo(); + m_lua_debug_hook_count = 100; + m_lua_debug_hook_yield = 50; + m_lua_debug_hook_send_evt = false; + m_lua_debug_hook = 0; + + m_evtHandler = NULL; + m_id = wxID_ANY; + // let the list delete these items m_pDerivedList->DeleteContents(true); *************** *** 254,257 **** --- 548,555 ---- wxLuaStateRefData::wxLuaStateRefData() { + #ifdef WXLUA_THREAD_INTERCEPTION + wxLuaState_SetupThreadHandlers(); + #endif //WXLUA_THREAD_INTERCEPTION + Init(); } *************** *** 263,266 **** --- 561,567 ---- wxLuaStateRefData::~wxLuaStateRefData() { + // no events here, the handler may already be gone + m_evtHandler = NULL; + CloseLuaState(true); *************** *** 338,342 **** wxLuaCallback *pCallback = (wxLuaCallback *) node->GetData(); wxCHECK_RET(pCallback, wxT("Invalid wxLuaCallback")); ! pCallback->ClearLuaState(); node = node->GetNext(); --- 639,644 ---- wxLuaCallback *pCallback = (wxLuaCallback *) node->GetData(); wxCHECK_RET(pCallback, wxT("Invalid wxLuaCallback")); ! if (pCallback->GetwxLuaState().GetRefData() != this) ! pCallback->ClearLuaState(); node = node->GetNext(); *************** *** 348,352 **** wxLuaDestroyCallback *pCallback = (wxLuaDestroyCallback *) node->GetData(); wxCHECK_RET(pCallback, wxT("Invalid wxLuaCallback")); ! pCallback->ClearLuaState(); node = node->GetNext(); --- 650,655 ---- wxLuaDestroyCallback *pCallback = (wxLuaDestroyCallback *) node->GetData(); wxCHECK_RET(pCallback, wxT("Invalid wxLuaCallback")); ! if (pCallback->GetwxLuaState().GetRefData() != this) ! pCallback->ClearLuaState(); node = node->GetNext(); *************** *** 417,425 **** } ! bool wxLuaState::Create() { ! UnRef(); m_refData = new wxLuaStateRefData(); lua_State* L = lua_open(); M_WXLSTATEDATA->m_lua_State = L; --- 720,731 ---- } ! bool wxLuaState::Create(wxEvtHandler *handler, wxWindowID id) { ! Destroy(); m_refData = new wxLuaStateRefData(); + M_WXLSTATEDATA->m_evtHandler = handler; + M_WXLSTATEDATA->m_id = id; + lua_State* L = lua_open(); M_WXLSTATEDATA->m_lua_State = L; *************** *** 443,448 **** lua_settable( L, LUA_REGISTRYINDEX ); ! /* ! // register handlers to send events FIXME if (!M_WXLSTATEDATA->m_lua_State_static) { --- 749,753 ---- lua_settable( L, LUA_REGISTRYINDEX ); ! // register handlers to send events if (!M_WXLSTATEDATA->m_lua_State_static) { *************** *** 451,458 **** RegisterFunction(LuaTraceback, wxT("_TRACEBACK")); } - */ // now register bindings RegisterBindings(true); return true; } --- 756,767 ---- RegisterFunction(LuaTraceback, wxT("_TRACEBACK")); } // now register bindings RegisterBindings(true); + + // alert people that we've been created so they can finish setting us up + wxLuaEvent event(wxEVT_LUA_CREATION, GetId(), *this); + SendEvent( event ); + return true; } *************** *** 461,465 **** { wxCHECK_MSG(L != NULL, false, wxT("Invalid lua_State")); ! if (GetRefData() != NULL) UnRef(); if (type == WXLUASTATE_ATTACH) --- 770,774 ---- { wxCHECK_MSG(L != NULL, false, wxT("Invalid lua_State")); ! if (GetRefData() != NULL) Destroy(); if (type == WXLUASTATE_ATTACH) *************** *** 485,489 **** // delete reference to old data ! UnRef(); // reference new data --- 794,798 ---- // delete reference to old data ! Destroy(); // reference new data *************** *** 505,508 **** --- 814,828 ---- } + void wxLuaState::Destroy() + { + if (!GetRefData()) return; + + // we don't want recursion in UnRef and wxLua_lua_garbageCollect + if (GetRefData()->GetRefCount() == 1) + M_WXLSTATEDATA->CloseLuaState(true); + + UnRef(); + } + bool wxLuaState::CloseLuaState(bool force) { *************** *** 523,526 **** --- 843,1050 ---- } + void wxLuaState::SetEventHandler(wxEvtHandler *evtHandler) + { + wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); + M_WXLSTATEDATA->m_evtHandler = evtHandler; + } + wxEvtHandler *wxLuaState::GetEventHandler() const + { + wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_evtHandler; + } + + void wxLuaState::SetId(wxWindowID id) + { + wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); + M_WXLSTATEDATA->m_id = id; + } + wxWindowID wxLuaState::GetId() const + { + wxCHECK_MSG(Ok(), wxID_ANY, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_id; + } + + void wxLuaState::DisplayError( const wxString &errorMsg ) + { + wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), this); + event.SetString(errorMsg); + SendEvent( event ); + } + + bool wxLuaState::CheckRunError(int rc) + { + wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState")); + + wxString msg; + if (!CheckRunError(rc, &msg)) + { + wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), this); + event.SetString(msg); + event.SetInt(-1); // don't know what line the error occured + SendEvent( event ); + return false; + } + return true; + } + + void wxLuaState::SendEvent( wxLuaEvent &event ) const + { + wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); + if (GetEventHandler()) + { + event.SetEventObject( (wxObject*)this ); + GetEventHandler()->ProcessEvent(event); + } + } + + // ---------------------------------------------------------------------------- + + int wxLuaState::RunFile(const wxString &filename) + { + wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); + wxCHECK_MSG(!M_WXLSTATEDATA->m_is_running, -1, wxT("lua interpreter is already running")); + M_WXLSTATEDATA->m_debug_hook_break = false; + + M_WXLSTATEDATA->m_is_running = true; + // int ret_val = lua_dofile(m_lua_State, wx2lua(filename)); + int ret_val = LuaDoFile(filename); // FIXME use LuaDoFile in RunFile ? + M_WXLSTATEDATA->m_is_running = false; + if (!M_WXLSTATEDATA->m_debug_hook_break) + (void)CheckRunError(ret_val); + + M_WXLSTATEDATA->m_debug_hook_break = false; + return ret_val; + } + + int wxLuaState::RunString(const wxString &script, const wxString& WXUNUSED(name)) + { + wxCHECK_MSG(Ok(), -1, wxT("Invalid wxLuaState")); + wxCHECK_MSG(!M_WXLSTATEDATA->m_is_running, -1, wxT("lua interpreter is already running")); + M_WXLSTATEDATA->m_debug_hook_break = false; + + M_WXLSTATEDATA->m_is_running = true; + //int ret_val = luaL_loadbuffer(m_lua_State, wx2lua(script), script.Len(), wx2lua(name)); + int ret_val = lua_dostring(GetLuaState(), wx2lua(script)); + M_WXLSTATEDATA->m_is_running = false; + + // if it's been stopped then don't send this error message, already sent stopped one + if (!M_WXLSTATEDATA->m_debug_hook_break) + (void)CheckRunError(ret_val); + + M_WXLSTATEDATA->m_debug_hook_break = false; + return ret_val; + } + + int wxLuaState::RunBuffer(const unsigned char buf[], size_t size, const wxString &name) + { + wxCHECK_MSG(Ok(), -1, wxT("Invalid wxLuaState")); + wxCHECK_MSG(!M_WXLSTATEDATA->m_is_running, -1, wxT("lua interpreter is already running")); + M_WXLSTATEDATA->m_debug_hook_break = false; + + M_WXLSTATEDATA->m_is_running = true; + //int ret_val = luaL_loadbuffer(m_lua_State, (const char*)buf, size, wx2lua(name)); + int ret_val = lua_dobuffer(GetLuaState(), (const char*)buf, size, wx2lua(name)); + M_WXLSTATEDATA->m_is_running = false; + + if (!M_WXLSTATEDATA->m_debug_hook_break) + (void)CheckRunError(ret_val); + + M_WXLSTATEDATA->m_debug_hook_break = false; + return ret_val; + } + + bool wxLuaState::IsRunning() const + { + wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_is_running; + } + + void wxLuaState::DebugHookBreak(const wxString &msg) + { + wxCHECK_RET(Ok(), wxT("Inval")); + wxCHECK_RET(M_WXLSTATEDATA->m_is_running, wxT("lua interpreter not running")); + + // Lua likes to be stopped within the debug hook, you get funny wxYield + // recursion asserts if you call terror() within another wxYield, ie. from a gui button + + M_WXLSTATEDATA->m_debug_hook_break_msg = msg; + M_WXLSTATEDATA->m_debug_hook_break = true; + SetLuaDebugHook(1, -1, false); + M_WXLSTATEDATA->m_is_running = false; + } + + bool wxLuaState::GetDebugHookBreak() const + { + wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_debug_hook_break; + } + wxString wxLuaState::GetDebugHookBreakMessage() const + { + wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_debug_hook_break_msg; + } + + // ---------------------------------------------------------------------------- + + void wxLuaState::SetLuaDebugHook(int count, int yield, bool send_debug_evt, int hook) + { + wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); + + M_WXLSTATEDATA->m_lua_debug_hook_count = count; + M_WXLSTATEDATA->m_lua_debug_hook_yield = yield; + M_WXLSTATEDATA->m_lua_debug_hook_send_evt = send_debug_evt; + M_WXLSTATEDATA->m_lua_debug_hook = hook; + + if (count > 0) + { + // These are the various hooks you can install + //LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, and LUA_MASKCOUNT + //lua_sethook(m_lua_State, LuaDebugHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0); + lua_sethook(GetLuaState(), LuaDebugHook, hook, count); + } + else + lua_sethook(GetLuaState(), LuaDebugHook, 0, 0); // disable hook + } + + int wxLuaState::GetLuaDebugHookCount() const + { + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_lua_debug_hook_count; + } + int wxLuaState::GetLuaDebugHookYield() const + { + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_lua_debug_hook_yield; + } + bool wxLuaState::GetLuaDebugHookSendEvt() const + { + wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_lua_debug_hook_send_evt; + } + int wxLuaState::GetLuaDebugHook() const + { + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_lua_debug_hook; + } + + unsigned long wxLuaState::GetLastLuaDebugHookTime() const + { + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState")); + return M_WXLSTATEDATA->m_last_debug_hook_time; + } + void wxLuaState::SetLastLuaDebugHookTime(unsigned long t) + { + wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); + M_WXLSTATEDATA->m_last_debug_hook_time = t; + } + + // ---------------------------------------------------------------------------- + + void wxLuaState::RegisterFunction(lua_CFunction func, const wxString &funcName) + { + wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); + lua_register( GetLuaState(), wx2lua(funcName), func ); + } + void wxLuaState::RegisterBindings(bool registerTypes) { *************** *** 1613,1625 **** } - #if 1 // defined(LUA_EMBEDDED) // FIXME - who gets the error message? - #define LUAERROR_OUTPUT(msg) \ - wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); \ - luaInterpreter->DisplayError(msg); - #else - #define LUAERROR_OUTPUT(msg) \ - wxLuaHandler::GetHandler().DisplayError(msg); - #endif - int wxLuaState::LuaError(int status, int top) { --- 2137,2140 ---- *************** *** 1649,1653 **** errorMsg += wxT("\n"); ! LUAERROR_OUTPUT(errorMsg) lua_settop(L, top); status = 0; --- 2164,2168 ---- errorMsg += wxT("\n"); ! DisplayError(errorMsg); lua_settop(L, top); status = 0; Index: wxlbind.cpp =================================================================== RCS file: /cvsroot/wxlua/wxLua/modules/wxlua/src/wxlbind.cpp,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** wxlbind.cpp 16 Dec 2005 05:12:26 -0000 1.9 --- wxlbind.cpp 22 Dec 2005 18:42:35 -0000 1.10 *************** *** 251,257 **** } ! void wxLuaBinding::UnRegisterBinding(const wxLuaState& wxlState) { - lua_State *L = wxlState.GetLuaState(); lua_pushstring(L, wx2lua(nameSpace)); lua_pushnil(L); --- 251,256 ---- } ! void wxLuaBinding::UnRegisterBinding(lua_State* L) { lua_pushstring(L, wx2lua(nameSpace)); lua_pushnil(L); Index: wxlintrp.cpp =================================================================== RCS file: /cvsroot/wxlua/wxLua/modules/wxlua/src/wxlintrp.cpp,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** wxlintrp.cpp 18 Dec 2005 18:04:38 -0000 1.10 --- wxlintrp.cpp 22 Dec 2005 18:42:35 -0000 1.11 *************** *** 30,356 **** #include "wxlua/include/internal.h" - extern bool wxLuaCleanupWindows(wxList *list, bool only_check); // in wxlstate.cpp - - wxHashMapLuaInterpreter s_wxHashMapLuaInterpreter; - - // add lua_States created from lua's coroutines - #define WXLUA_THREAD_INTERCEPTION - - extern "C" - { - #include "lua/include/lua.h" - #include "lua/include/lauxlib.h" - #include "lua/include/lualib.h" - - #ifdef WXLUA_THREAD_INTERCEPTION - // See lua/src/lstate.c for added hook into luaE_newthread() - #include "lua/include/luathread.h" - #endif //WXLUA_THREAD_INTERCEPTION - } - - #ifdef WXLUA_THREAD_INTERCEPTION - - // Hook into function calls to luaE_newthread (calls from coroutine.create/wrap) - // and add the new lua_State as a child sharing it's wxLuaStateVariables - void wxLuaInterpreter_newthread_handler(lua_State *L, lua_State *L1) - { - // L is the original lua_State, L1 new child thread - wxLuaState wxlState(L); - wxCHECK_RET(wxlState.Ok(), wxT("Invalid wxLuaState")); - - // put into the hashmap - wxLuaStateRefData::s_wxHashMapLuaStateRefData[L1] = wxlState.GetLuaStateRefData(); - - // Stick us into the lua_State - push key, value - lua_pushstring( L1, "__wxLuaStateRefData" ); - lua_pushlightuserdata( L1, (void*)wxlState.GetRefData() ); - // set the value - lua_settable( L1, LUA_REGISTRYINDEX ); - - wxLuaInterpreter *L_interp = wxFindLuaInterpreter(L); - wxPrintf(wxT("wxLuaInterpreter_newthread_handler new lua_State from a thread L=%ld L1=%ld\n"), (long)L, (long)L1); - - if (L_interp != NULL) - { - s_wxHashMapLuaInterpreter[L1] = L_interp; - - // Stick us into the lua interpreter - push key, value - lua_pushstring( L1, "__wxLuaInterpreter" ); - lua_pushlightuserdata( L1, L_interp); - // set the value - lua_settable( L1, LUA_REGISTRYINDEX ); - } - } - - // Hook into function calls to luaE_freethread (calls from coroutine.create/wrap) - // and remove the child lua_State - void wxLuaInterpreter_freethread_handler(lua_State *WXUNUSED(L), lua_State *L1) - { - // L is the original lua_State, L1 child thread, don't remove L - //wxPrintf(wxT("wxLuaInterpreter_freethread_handler lua_State from a thread L=%ld L1=%ld\n"), (long)L, (long)L1); fflush(stdout); - wxLuaStateRefData::s_wxHashMapLuaStateRefData.erase(L1); - s_wxHashMapLuaInterpreter.erase(L1); - } - - static void setupthreadhandlers() - { - if (luaX_getnewthreadhandler() == NULL) - luaX_setnewthreadhandler( wxLuaInterpreter_newthread_handler ); - if (luaX_getfreethreadhandler() == NULL) - luaX_setfreethreadhandler( wxLuaInterpreter_freethread_handler ); - } - - #endif //WXLUA_THREAD_INTERCEPTION - - // ---------------------------------------------------------------------------- - // Extra wxLua helpers that use the lua_State to find owner wxLuaInterpreter - // ---------------------------------------------------------------------------- - - wxLuaInterpreter *wxFindLuaInterpreter(lua_State *L) - { - int top = lua_gettop( L ); - - // try to get the state - lua_pushstring( L, "__wxLuaInterpreter" ); - lua_gettable( L, LUA_REGISTRYINDEX ); - - // if nothing was returned or it wasn't a ptr, abort - if ( top == lua_gettop(L) || !lua_islightuserdata(L, -1) ) - { - lua_settop( L, top ); - return NULL; - } - // get the pointer, clean the stack, return - wxLuaInterpreter* lI = (wxLuaInterpreter*)lua_touserdata( L, -1 ); - lua_settop( L, top ); - return lI; - } - // ---------------------------------------------------------------------------- // lua hooks and function replacements for embedding into wxWidgets // ---------------------------------------------------------------------------- - int LuaPrint( lua_State *L ) - { - wxString msg; - int i, n = lua_gettop(L); - - // figure out the types here in c++ land - lua_getglobal(L, "tostring"); - for (i = 1; i <= n; i++) - { - if (i > 1) msg.Append(wxT(", ")); - - if (lua_isstring(L, i)) - msg += lua2wx(lua_tostring(L, i)); - else if (lua_isnumber(L, i)) - msg += wxString::Format(wxT("%lf"), lua_tonumber(L, i)); - else if (lua_iscfunction(L, i)) - msg += wxString::Format(wxT("C function %ld"), (long int)lua_tocfunction(L, i)); - else if (lua_isuserdata(L, i)) - msg += wxString::Format(wxT("User data %ld"), (long int)lua_touserdata(L, i)); - else if (lua_isboolean(L, i)) - msg += lua_toboolean(L,i) ? wxT("true") : wxT("false"); - else if (lua_isnil(L,i)) - msg += wxT("nil"); - else if (lua_isnone(L,i)) - msg += wxT("unknown"); - else - msg += wxString::Format(wxT("%s:%p"), lua_typename(L,lua_type(L,i)), lua_topointer(L,i)); - } - - if (!msg.IsEmpty()) - { - wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); - - if (luaInterpreter) - { - wxLuaEvent event(wxEVT_LUA_CONSOLE, luaInterpreter->GetId(), luaInterpreter); - event.SetString(msg); - luaInterpreter->SendEvent( event ); - } - } - - return 0; // no items put onto stack - } - - // copied from the Lua 5.0.1 debug library - #define LEVELS1 12 /* size of the first part of the stack */ - #define LEVELS2 10 /* size of the second part of the stack */ - - // copied from the Lua 5.0.1 debug library - int LuaTraceback(lua_State *L) - { - int level = 1; // skip level 0 (it's this function) - int firstpart = 1; // still before eventual `...' - lua_Debug ar; - if (lua_gettop(L) == 0) - lua_pushliteral(L, ""); - else if (!lua_isstring(L, 1)) // no string message - return 1; - else - lua_pushliteral(L, "\n"); - - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L, level++, &ar)) - { - if (level > LEVELS1 && firstpart) - { - // no more than `LEVELS2' more levels? - if (!lua_getstack(L, level+LEVELS2, &ar)) - level--; // keep going - else - { - lua_pushliteral(L, "\n\t..."); // too many levels - while (lua_getstack(L, level+LEVELS2, &ar)) // find last levels - level++; - } - firstpart = 0; - continue; - } - lua_pushliteral(L, "\n\t"); - lua_getinfo(L, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - switch (*ar.namewhat) - { - case 'g': // global - case 'l': // local - case 'f': // field - case 'm': // method - lua_pushfstring(L, " in function `%s'", ar.name); - break; - default: { - if (*ar.what == 'm') // main? - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C' || *ar.what == 't') - lua_pushliteral(L, " ?"); // C function or tail call - else - lua_pushfstring(L, " in function <%s:%d>", - ar.short_src, ar.linedefined); - } - } - lua_concat(L, lua_gettop(L)); - } - lua_concat(L, lua_gettop(L)); - return 1; - } - - int LuaAlert( lua_State *L ) - { - wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); - - if (luaInterpreter) - { - wxString msg = lua2wx(lua_tostring(L, 1)); - - wxLuaEvent event(wxEVT_LUA_ERROR, luaInterpreter->GetId(), luaInterpreter); - event.SetString(msg); - - long line = -1; - wxString lineStr = msg; - - // Why can't I fill a lua_Debug here? Try to get the line number - // by parsing the error message that looks like this, 1 is linenumber - // [string "a = 1("]:1: unexpected symbol near `<eof>' - while(!lineStr.IsEmpty()) - { - lineStr = lineStr.AfterFirst(wxT(']')); - if ((lineStr.Length() > 0) && (lineStr.GetChar(0) == wxT(':'))) - { - lineStr = lineStr.AfterFirst(wxT(':')); - if (lineStr.IsEmpty() || lineStr.BeforeFirst(wxT(':')).ToLong(&line)) - break; - } - } - - event.SetInt((int)line); - luaInterpreter->SendEvent( event ); - } - - return 0; - } - - void LuaDebugHook(lua_State *L, lua_Debug *LDebug) - { - wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); - - // during program shutdown this can be called - ignore it - if (luaInterpreter == NULL) - return; - - // FIXME - for select event types we don't want to do anything - wxEventType evtType = luaInterpreter->GetwxLuaState().GetInEventType(); - if ((evtType != wxEVT_NULL)) - //(evtType == wxEVT_IDLE) && (evtType == wxEVT_PAINT) && - //(evtType == wxEVT_DESTROY) && (evtType == wxEVT_CLOSE_WINDOW)) - return; - - // they want to break the program, restore old debug hook, then error out - if (luaInterpreter->GetBreak()) - { - // restore hook to previous state see wxLuaInterpreter::Break() - luaInterpreter->SetLuaDebugHook(luaInterpreter->GetLuaDebugHookCount(), - luaInterpreter->GetLuaDebugHookYield(), - luaInterpreter->GetLuaDebugHookSendEvt(), - luaInterpreter->GetLuaDebugHook()); - - terror(L, wx2lua(luaInterpreter->GetBreakMessage())); - return; - } - - if (luaInterpreter->GetLuaDebugHookSendEvt()) - { - int ret = 0; - ret = lua_getinfo(L, "l", LDebug); // line (ldebug.currentline) - - wxLuaEvent event(wxEVT_LUA_DEBUG_HOOK, luaInterpreter->GetId(), luaInterpreter); - event.m_lua_Debug = LDebug; - event.SetInt(LDebug->currentline); - luaInterpreter->SendEvent( event ); - if (event.m_stop_interpreter) - terror(L, "Interpreter stopped"); - } - - // Try to yield *after* sending event to allow C++ gui update - if (luaInterpreter->GetLuaDebugHookYield() > 0) - { - // yield based on number of ms passed NOT every hook event - unsigned long last_time = luaInterpreter->GetLastLuaDebugHookTime(); - unsigned long cur_time = wxGetLocalTimeMillis().GetLo(); - - if ((cur_time > last_time + luaInterpreter->GetLuaDebugHookYield()) || - (cur_time < last_time)) // wrapped - { - luaInterpreter->SetLastLuaDebugHookTime( cur_time ); - - bool painting = false; - - #if WXWIN_COMPATIBILITY_24 || !wxCHECK_VERSION(2, 5, 0) - wxNode* node; - #else - wxHashTable::Node* node; - #endif - - // FIXME - wxGTK crashes if wxYield[IfNeeded] is called within a paint handler? I think - luaInterpreter->GetwxLuaState().GetLuaStateRefData()->m_pTrackedList->BeginFind(); - node = luaInterpreter->GetwxLuaState().GetLuaStateRefData()->m_pTrackedList->Next(); - while (node) - { - if (wxDynamicCast(node->GetData(), wxPaintDC)) - { - painting = true; - break; - } - node = luaInterpreter->GetwxLuaState().GetLuaStateRefData()->m_pTrackedList->Next(); - } - - if (!painting) - wxYieldIfNeeded(); - } - } - } - //----------------------------------------------------------------------------- // wxLuaEvent --- 30,37 ---- *************** *** 366,630 **** DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_SHUTDOWN) ! wxLuaEvent::wxLuaEvent(wxEventType commandType, wxWindowID id, wxLuaInterpreter *interpreter) : wxNotifyEvent(commandType, id) { ! m_luaInterpreter = interpreter; m_lua_Debug = NULL; m_stop_interpreter = false; } - - //----------------------------------------------------------------------------- - // wxLuaInterpreter - //----------------------------------------------------------------------------- - IMPLEMENT_ABSTRACT_CLASS(wxLuaInterpreter, wxObject) - - wxLuaInterpreter::wxLuaInterpreter() : wxObject() - { - Init(); - } - wxLuaInterpreter::wxLuaInterpreter(wxEvtHandler *handler, wxWindowID id) : wxObject() - { - Init(); - Create(handler, id); - } - - void wxLuaInterpreter::Init() - { - #ifdef WXLUA_THREAD_INTERCEPTION - setupthreadhandlers(); - #endif //WXLUA_THREAD_INTERCEPTION - - m_is_running = false; - m_user_break = false; - - m_last_debug_hook_time = wxGetLocalTimeMillis().GetLo(); - - m_id = wxID_ANY; - m_evtHandler = NULL; - - m_lua_debug_hook_count = 100; - m_lua_debug_hook_yield = 50; - m_lua_debug_hook_send_evt = false; - m_lua_debug_hook = 0; - } - - bool wxLuaInterpreter::Create(lua_State *inL, wxEvtHandler *handler, wxWindowID id) - { - if (Ok() && !Destroy(true)) - return false; - - m_evtHandler = handler; - m_id = id; - - // create a lua instance - if (inL != NULL) - { - m_wxlState = wxLuaState(inL, WXLUASTATE_SETSTATE); - } - else - { - m_wxlState = wxLuaState(true); - } - - s_wxHashMapLuaInterpreter[m_wxlState.GetLuaState()] = this; - - // Stick us into the lua interpreter - push key, value - lua_pushstring( m_wxlState.GetLuaState(), "__wxLuaInterpreter" ); - lua_pushlightuserdata( m_wxlState.GetLuaState(), (void*)this ); - // set the value - lua_settable( m_wxlState.GetLuaState(), LUA_REGISTRYINDEX ); - - // register handlers to send events - if (inL == NULL) - { - RegisterFunction(LuaPrint, wxT("print")); - RegisterFunction(LuaAlert, wxT("_ALERT")); - RegisterFunction(LuaTraceback, wxT("_TRACEBACK")); - } - - // alert people that we've been created so they can finish setting us up - wxLuaEvent event(wxEVT_LUA_CREATION, GetId(), this); - SendEvent( event ); - - return true; - } - - wxLuaInterpreter::~wxLuaInterpreter() - { - if (Ok()) - { - m_evtHandler = NULL; // no events here, the handler may already be gone - Destroy(true); - } - } - - void wxLuaInterpreter::GarbageCollectWindows(bool closeWindows) - { - // remove deleted windows - if (Ok()) m_wxlState.GarbageCollectWindows(closeWindows); - } - - bool wxLuaInterpreter::Destroy(bool force) - { - wxCHECK_MSG(Ok(), false, wxT("Interpreter not created")); - wxCHECK_MSG(!m_is_running, false, wxT("Interpreter still running, can't destroy")); - - // remember pointer value, even though CloseLuaState actually frees it - lua_State* L = m_wxlState.GetLuaState(); - - if (!m_wxlState.CloseLuaState(force)) - return false; - - s_wxHashMapLuaInterpreter.erase(L); - m_evtHandler = NULL; - - return true; - } - - bool wxLuaInterpreter::Ok() const - { - return m_wxlState.Ok(); - } - - void wxLuaInterpreter::SetEventHandler(wxEvtHandler *evtHandler) - { - m_evtHandler = evtHandler; - } - - int wxLuaInterpreter::RunFile(const wxString &filename) - { - wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); - wxCHECK_MSG(!m_is_running, -1, wxT("lua interpreter is already running")); - m_user_break = false; - - m_is_running = true; - // int ret_val = lua_dofile(m_lua_State, wx2lua(filename)); - int ret_val = LuaDoFile(m_wxlState.GetLuaState(), filename); // FIXME use LuaDoFile in RunFile ? - m_is_running = false; - if (!m_user_break) - (void)CheckRunError(ret_val); - - m_user_break = false; - return ret_val; - } - - int wxLuaInterpreter::RunString(const wxString &script, const wxString& WXUNUSED(name)) - { - wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); - wxCHECK_MSG(!m_is_running, -1, wxT("lua interpreter is already running")); - m_user_break = false; - - m_is_running = true; - //int ret_val = luaL_loadbuffer(m_lua_State, wx2lua(script), script.Len(), wx2lua(name)); - int ret_val = lua_dostring(m_wxlState.GetLuaState(), wx2lua(script)); - m_is_running = false; - - // if it's been stopped then don't send this error message, already sent stopped one - if (!m_user_break) - (void)CheckRunError(ret_val); - - m_user_break = false; - return ret_val; - } - - int wxLuaInterpreter::RunBuffer(const unsigned char buf[], size_t size, const wxString &name) - { - wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); - wxCHECK_MSG(!m_is_running, -1, wxT("lua interpreter is already running")); - m_user_break = false; - - m_is_running = true; - //int ret_val = luaL_loadbuffer(m_lua_State, (const char*)buf, size, wx2lua(name)); - int ret_val = lua_dobuffer(GetLuaState(), (const char*)buf, size, wx2lua(name)); - m_is_running = false; - - if (!m_user_break) - (void)CheckRunError(ret_val); - - m_user_break = false; - return ret_val; - } - - void wxLuaInterpreter::Break(const wxString &msg) - { - wxCHECK_RET(Ok(), wxT("lua interpreter not created")); - wxCHECK_RET(m_is_running, wxT("lua interpreter not running")); - - // Lua likes to be stopped within the debug hook, you get funny wxYield - // recursion asserts if you call terror() within another wxYield, ie. from a gui button - - m_break_msg = msg; - m_user_break = true; - SetLuaDebugHook(1, -1, false); - m_is_running = false; - } - - void wxLuaInterpreter::SetLuaDebugHook(int count, int yield, bool send_debug_evt, int hook) - { - wxCHECK_RET(Ok(), wxT("lua interpreter not created")); - - m_lua_debug_hook_count = count; - m_lua_debug_hook_yield = yield; - m_lua_debug_hook_send_evt = send_debug_evt; - m_lua_debug_hook = hook; - - if (count > 0) - { - // These are the various hooks you can install - //LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, and LUA_MASKCOUNT - //lua_sethook(m_lua_State, LuaDebugHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0); - lua_sethook(m_wxlState.GetLuaState(), LuaDebugHook, hook, count); - } - else - lua_sethook(GetLuaState(), LuaDebugHook, 0, 0); // disable hook - } - - unsigned long wxLuaInterpreter::GetLastLuaDebugHookTime() const - { - return m_last_debug_hook_time; - } - void wxLuaInterpreter::SetLastLuaDebugHookTime(unsigned long t) - { - m_last_debug_hook_time = t; - } - - lua_State *wxLuaInterpreter::GetLuaState() const - { - return m_wxlState.GetLuaState(); - } - - void wxLuaInterpreter::RegisterFunction(lua_CFunction func, const wxString &funcName) - { - wxCHECK_RET(Ok(), wxT("lua interpreter not created")); - lua_register( GetLuaState(), wx2lua(funcName), func ); - } - - void wxLuaInterpreter::DisplayError( const wxString &errorMsg ) - { - wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), this); - event.SetString(errorMsg); - SendEvent( event ); - } - - bool wxLuaInterpreter::CheckRunError(int rc) - { - wxString msg; - if (!wxLuaState::CheckRunError(rc, &msg)) - { - wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), this); - event.SetString(msg); - event.SetInt(-1); // don't know what line the error occured - SendEvent( event ); - return false; - } - return true; - } - - void wxLuaInterpreter::SendEvent( wxLuaEvent &event ) const - { - if (GetEventHandler()) - { - event.SetEventObject( (wxObject*)this ); - GetEventHandler()->ProcessEvent(event); - } - } --- 47,55 ---- DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_SHUTDOWN) ! wxLuaEvent::wxLuaEvent(wxEventType commandType, wxWindowID id, const wxLuaState& wxlState) : wxNotifyEvent(commandType, id) { ! m_wxlState = wxlState; m_lua_Debug = NULL; m_stop_interpreter = false; } |