wxldtarg.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 // Purpose:     Implements the client end of wxLua debugging session
00003 // Author:      J. Winwood, John Labenski, Ray Gilbert
00004 // Created:     May 2002
00005 // RCS-ID:      $Id: wxldtarg.cpp,v 1.47 2008/03/26 05:23:48 jrl1 Exp $
00006 // Copyright:   (c) 2002 Lomtick Software. All rights reserved.
00007 // Licence:     wxWidgets licence
00008 /////////////////////////////////////////////////////////////////////////////
00009 
00010 #include "wx/wxprec.h"
00011 
00012 #ifdef __BORLANDC__
00013     #pragma hdrstop
00014 #endif
00015 
00016 #ifndef WX_PRECOMP
00017     #include "wx/wx.h"
00018 #endif
00019 
00020 #include "wxluasocket/include/wxldtarg.h"
00021 #include "wxluasocket/include/wxldserv.h"
00022 
00023 #if !wxCHECK_VERSION(2, 6, 0)
00024     #define wxMilliSleep wxUsleep
00025 #endif // !wxCHECK_VERSION(2, 6, 0)
00026 
00027 #define WXLUASOCKET_CONNECT_TIMEOUT 200       // 20 seconds
00028 
00029 // ----------------------------------------------------------------------------
00030 // wxLuaDebugTarget::LuaThread
00031 // ----------------------------------------------------------------------------
00032 
00033 void *wxLuaDebugTarget::LuaThread::Entry()
00034 {
00035     m_pTarget->ThreadFunction();
00036     //m_pTarget->m_pThread = NULL;
00037     return 0;
00038 }
00039 
00040 // ----------------------------------------------------------------------------
00041 // wxLuaDebugTarget - Handles Debugger/Debuggee IO
00042 // ----------------------------------------------------------------------------
00043 
00044 wxLuaDebugTarget::wxLuaDebugTarget(const wxLuaState& wxlState,
00045                                    const wxString &serverName,
00046                                    int             port_number) :
00047     m_wxlState(wxlState),
00048     m_port_number(port_number),
00049     m_serverName(serverName),
00050     m_debugCondition(m_debugMutex),
00051     m_forceBreak(false),
00052     m_resetRequested(false),
00053     m_fConnected(false),
00054     m_fRunning(false),
00055     m_fStopped(false),
00056     m_fExiting(false),
00057     m_fErrorsSeen(false),
00058     m_nFramesUntilBreak(0),
00059     m_runCondition(m_runMutex),
00060     m_pThread(NULL)
00061 {
00062     m_clientSocket.m_name = wxString::Format(wxT("wxLuaDebugTarget::m_clientSocket (%ld)"), (long)wxGetProcessId());
00063 
00064     lua_State* L = m_wxlState.GetLuaState();
00065     // Stick us into the lua_State - push key, value
00066     lua_pushstring( L, "__wxLuaDebugTarget__" );
00067     lua_pushlightuserdata( L, (void*)this );
00068     // set the value
00069     lua_rawset( L, LUA_REGISTRYINDEX );
00070 
00071     lua_sethook(L, LuaDebugHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
00072 
00073     lua_pushcfunction(L, LuaPrint);
00074     lua_setglobal(L, "print");
00075 
00076     EnterLuaCriticalSection();
00077 }
00078 
00079 wxLuaDebugTarget::~wxLuaDebugTarget()
00080 {
00081     //if (m_pThread != NULL)
00082     //    delete m_pThread;
00083 
00084     LeaveLuaCriticalSection();
00085 }
00086 
00087 bool wxLuaDebugTarget::IsConnected(bool wait_for_connect) const
00088 {
00089     if (m_fConnected || !wait_for_connect) return m_fConnected;
00090 
00091     for (int idx = 0; idx < WXLUASOCKET_CONNECT_TIMEOUT; ++idx)
00092     {
00093         if (m_fConnected)
00094             break;
00095 
00096         wxMilliSleep(100);
00097     }
00098     return m_fConnected;
00099 }
00100 
00101 bool wxLuaDebugTarget::Run()
00102 {
00103     wxCHECK_MSG(m_pThread == NULL, false, wxT("wxLuaDebugTarget::Run already called"));
00104 
00105     // Assume something is going to go wrong
00106     m_fErrorsSeen = true;
00107 
00108     m_pThread = new LuaThread(this);
00109     // Start the thread
00110     if ((m_pThread != NULL) &&
00111         (m_pThread->Create() == wxTHREAD_NO_ERROR) &&
00112         (m_pThread->Run()    == wxTHREAD_NO_ERROR))
00113     {
00114         // Wait for the connection to the server to complete
00115         if (!IsConnected())
00116         {
00117             wxMessageBox(wxT("Unable to connect to server"), wxT("wxLua client"), wxOK | wxCENTRE, NULL);
00118         }
00119         else
00120         {
00121             // OK, now we can start running.
00122             m_runCondition.Wait();
00123 
00124             m_fRunning    = true;
00125             m_fErrorsSeen = false;
00126 
00127             size_t idx, count = m_bufferArray.GetCount();
00128             for (idx = 0; idx < count; ++idx)
00129             {
00130                 wxString luaBuffer = m_bufferArray.Item(idx);
00131                 wxString bufFilename = luaBuffer.BeforeFirst(wxT('\0'));
00132                 wxString buf =  luaBuffer.AfterFirst(wxT('\0'));
00133 
00134                 wxLuaCharBuffer char_buf(buf);
00135                 int rc = m_wxlState.LuaDoBuffer(char_buf, char_buf.Length(),
00136                                             wx2lua(bufFilename));
00137 
00138                 m_fErrorsSeen = (rc != 0);
00139                 if (m_fErrorsSeen)
00140                 {
00141                     NotifyError(wxlua_LUA_ERR_msg(rc));
00142                     break;
00143                 }
00144             }
00145 
00146             m_bufferArray.Clear();
00147         }
00148     }
00149 
00150     return !m_fErrorsSeen;
00151 }
00152 
00153 void wxLuaDebugTarget::Stop()
00154 {
00155     NotifyExit();
00156 
00157     if (m_fConnected)
00158     {
00159         m_clientSocket.Shutdown(SD_BOTH);
00160         wxMilliSleep(100);
00161         m_clientSocket.Close();
00162     }
00163 
00164     if (m_pThread)
00165         m_pThread->Wait();
00166 }
00167 
00168 void wxLuaDebugTarget::ThreadFunction()
00169 {
00170     bool fThreadRunning = false;
00171 
00172     if (m_clientSocket.Connect(m_serverName, m_port_number))
00173     {
00174         m_fConnected   = true;
00175         fThreadRunning = true;
00176     }
00177     else
00178     {
00179         return; // FIXME
00180     }
00181 
00182     while (fThreadRunning && !m_pThread->TestDestroy() && !m_resetRequested && !m_fExiting)
00183     {
00184         unsigned char debugCommand = 0; // wxLuaSocketDebuggerCommands_Type
00185         if (!m_clientSocket.ReadCmd(debugCommand) ||
00186             !HandleDebuggerCmd(debugCommand))
00187         {
00188             fThreadRunning = false;
00189         }
00190     }
00191 }
00192 
00193 bool wxLuaDebugTarget::HandleDebuggerCmd(int debugCommand)
00194 {
00195     bool ret = false;
00196 
00197     switch ((int)debugCommand)
00198     {
00199         case wxLUASOCKET_DEBUGGER_CMD_NONE :
00200         {
00201             // This is an error, but maybe we can continue?
00202             ret = true;
00203             break;
00204         }
00205         case wxLUASOCKET_DEBUGGER_CMD_ADD_BREAKPOINT:
00206         {
00207             wxString fileName;
00208             wxInt32  lineNumber = 0;
00209 
00210             if (m_clientSocket.ReadString(fileName) &&
00211                 m_clientSocket.ReadInt32(lineNumber))
00212             {
00213                 ret = AddBreakPoint(fileName, lineNumber);
00214             }
00215             break;
00216         }
00217         case wxLUASOCKET_DEBUGGER_CMD_REMOVE_BREAKPOINT:
00218         {
00219             wxString fileName;
00220             wxInt32  lineNumber = 0;
00221 
00222             if (m_clientSocket.ReadString(fileName) &&
00223                 m_clientSocket.ReadInt32(lineNumber))
00224             {
00225                 ret = RemoveBreakPoint(fileName, lineNumber);
00226             }
00227             break;
00228         }
00229         case wxLUASOCKET_DEBUGGER_CMD_CLEAR_ALL_BREAKPOINTS:
00230         {
00231             ret = ClearAllBreakPoints();
00232             break;
00233         }
00234         case wxLUASOCKET_DEBUGGER_CMD_RUN_BUFFER:
00235         {
00236             wxString fileName;
00237             wxString buffer;
00238 
00239             if (m_clientSocket.ReadString(fileName) &&
00240                 m_clientSocket.ReadString(buffer))
00241             {
00242                 ret = Run(fileName, buffer);
00243             }
00244             break;
00245         }
00246         case wxLUASOCKET_DEBUGGER_CMD_DEBUG_STEP:
00247         {
00248             ret = Step();
00249             break;
00250         }
00251         case wxLUASOCKET_DEBUGGER_CMD_DEBUG_STEPOVER:
00252         {
00253             ret = StepOver();
00254             break;
00255         }
00256         case wxLUASOCKET_DEBUGGER_CMD_DEBUG_STEPOUT:
00257         {
00258             ret = StepOut();
00259             break;
00260         }
00261         case wxLUASOCKET_DEBUGGER_CMD_DEBUG_CONTINUE:
00262         {
00263             m_forceBreak = false;
00264             ret = Continue();
00265             break;
00266         }
00267         case wxLUASOCKET_DEBUGGER_CMD_DEBUG_BREAK:
00268         {
00269             ret = Break();
00270             break;
00271         }
00272         case wxLUASOCKET_DEBUGGER_CMD_ENUMERATE_STACK:
00273         {
00274             ret = EnumerateStack();
00275             break;
00276         }
00277         case wxLUASOCKET_DEBUGGER_CMD_ENUMERATE_STACK_ENTRY:
00278         {
00279             wxInt32 stackRef = 0;
00280 
00281             if (m_clientSocket.ReadInt32(stackRef))
00282                 ret = EnumerateStackEntry(stackRef);
00283 
00284             break;
00285         }
00286         case wxLUASOCKET_DEBUGGER_CMD_ENUMERATE_TABLE_REF:
00287         {
00288             wxInt32 tableRef = 0;
00289             wxInt32 index    = 0;
00290             long    itemNode = 0;
00291 
00292             if (m_clientSocket.ReadInt32(tableRef) &&
00293                 m_clientSocket.ReadInt32(index) &&
00294                 m_clientSocket.ReadLong(itemNode))
00295             {
00296                 ret = EnumerateTable(tableRef, index, itemNode);
00297             }
00298             break;
00299         }
00300         case wxLUASOCKET_DEBUGGER_CMD_RESET:
00301         {
00302             ret = Reset();
00303             break;
00304         }
00305         case wxLUASOCKET_DEBUGGER_CMD_EVALUATE_EXPR:
00306         {
00307             wxInt32 exprRef = 0;
00308             wxString buffer;
00309 
00310             if (m_clientSocket.ReadInt32(exprRef) &&
00311                 m_clientSocket.ReadString(buffer))
00312             {
00313                 ret = EvaluateExpr(exprRef, buffer);
00314             }
00315             break;
00316         }
00317         case wxLUASOCKET_DEBUGGER_CMD_CLEAR_DEBUG_REFERENCES:
00318         {
00319             size_t idx, idxMax = m_references.GetCount();
00320             for (idx = 0; idx < idxMax; ++idx)
00321             {
00322                 int iItem = m_references.Item(idx);
00323                 m_wxlState.wxluaR_Unref(iItem, &wxlua_lreg_debug_refs_key);
00324             }
00325             m_references.Clear();
00326             ret = true;
00327             break;
00328         }
00329         case wxLUASOCKET_DEBUGGER_CMD_DISABLE_BREAKPOINT: // FIXME do something here
00330             ret = true;
00331             break;
00332         case wxLUASOCKET_DEBUGGER_CMD_ENABLE_BREAKPOINT: // FIXME do something here
00333             ret = true;
00334             break;
00335         default :
00336             wxFAIL_MSG(wxT("Invalid wxLuaSocketDebuggerCommands_Type in wxLuaDebugTarget::ThreadFunction"));
00337     }
00338 
00339     return ret;
00340 }
00341 
00342 wxString wxLuaDebugTarget::CreateBreakPoint(const wxString &fileName, int lineNumber) const
00343 {
00344     return wxString::Format(wxT("%d:"), lineNumber) + fileName;
00345 }
00346 
00347 bool wxLuaDebugTarget::AtBreakPoint(const wxString &fileName, int lineNumber) const
00348 {
00349     wxCriticalSectionLocker locker(m_breakPointListCriticalSection);
00350     return (m_breakPointList.Index(CreateBreakPoint(fileName, lineNumber)) != wxNOT_FOUND);
00351 }
00352 
00353 bool wxLuaDebugTarget::AddBreakPoint(const wxString &fileName, int lineNumber)
00354 {
00355     wxCriticalSectionLocker locker(m_breakPointListCriticalSection);
00356     m_breakPointList.Add(CreateBreakPoint(fileName, lineNumber));
00357     return true;
00358 }
00359 
00360 bool wxLuaDebugTarget::RemoveBreakPoint(const wxString &fileName, int lineNumber)
00361 {
00362     wxCriticalSectionLocker locker(m_breakPointListCriticalSection);
00363     m_breakPointList.Remove(CreateBreakPoint(fileName, lineNumber));
00364     return true;
00365 }
00366 
00367 bool wxLuaDebugTarget::ClearAllBreakPoints()
00368 {
00369     wxCriticalSectionLocker locker(m_breakPointListCriticalSection);
00370     m_breakPointList.Clear();
00371     return true;
00372 }
00373 
00374 bool wxLuaDebugTarget::Run(const wxString &fileName, const wxString &buffer)
00375 {
00376     m_bufferArray.Add(fileName + wxT('\0') + buffer);
00377     return true;
00378 }
00379 
00380 bool wxLuaDebugTarget::Step()
00381 {
00382     m_nextOperation = DEBUG_STEP;
00383 
00384     if (!m_fRunning)
00385         m_runCondition.Signal();
00386     else if (m_fStopped)
00387         m_debugCondition.Signal();
00388 
00389     return true;
00390 }
00391 
00392 bool wxLuaDebugTarget::StepOver()
00393 {
00394     m_nFramesUntilBreak = 0;
00395     m_nextOperation = DEBUG_STEPOVER;
00396 
00397     if (!m_fRunning)
00398         m_runCondition.Signal();
00399     else if (m_fStopped)
00400         m_debugCondition.Signal();
00401 
00402     return true;
00403 }
00404 
00405 bool wxLuaDebugTarget::StepOut()
00406 {
00407     m_nFramesUntilBreak = 1;
00408     m_nextOperation = DEBUG_STEPOVER;
00409 
00410     if (!m_fRunning)
00411         m_runCondition.Signal();
00412     else if (m_fStopped)
00413         m_debugCondition.Signal();
00414 
00415     return true;
00416 }
00417 
00418 bool wxLuaDebugTarget::Continue()
00419 {
00420     m_nextOperation = DEBUG_GO;
00421 
00422     if (!m_fRunning)
00423         m_runCondition.Signal();
00424     else if (m_fStopped)
00425         m_debugCondition.Signal();
00426 
00427     return true;
00428 }
00429 
00430 bool wxLuaDebugTarget::Break()
00431 {
00432     m_forceBreak = true;
00433     return true;
00434 }
00435 
00436 bool wxLuaDebugTarget::Reset()
00437 {
00438     NotifyExit();
00439 
00440     m_forceBreak     = true;
00441     m_resetRequested = true;
00442 
00443     if (!m_fRunning)
00444         m_runCondition.Signal();
00445     else if (m_fStopped)
00446         m_debugCondition.Signal();
00447 
00448     return true;
00449 }
00450 
00451 bool wxLuaDebugTarget::EnumerateStack()
00452 {
00453     wxLuaDebugData debugData(true);
00454 
00455     EnterLuaCriticalSection();
00456     debugData.EnumerateStack(m_wxlState);
00457     LeaveLuaCriticalSection();
00458 
00459     return NotifyStackEnumeration(debugData);
00460 }
00461 
00462 bool wxLuaDebugTarget::EnumerateStackEntry(int stackRef)
00463 {
00464     wxLuaDebugData debugData(true);
00465 
00466     EnterLuaCriticalSection();
00467     debugData.EnumerateStackEntry(m_wxlState, stackRef, m_references);
00468     LeaveLuaCriticalSection();
00469 
00470     return NotifyStackEntryEnumeration(stackRef, debugData);
00471 }
00472 
00473 bool wxLuaDebugTarget::EnumerateTable(int tableRef, int nIndex, long nItemNode)
00474 {
00475     wxLuaDebugData debugData(true);
00476 
00477     EnterLuaCriticalSection();
00478     debugData.EnumerateTable(m_wxlState, tableRef, nIndex, m_references);
00479     LeaveLuaCriticalSection();
00480 
00481     return NotifyTableEnumeration(nItemNode, debugData);
00482 }
00483 
00484 bool wxLuaDebugTarget::EvaluateExpr(int exprRef, const wxString &strExpr) // FIXME - check this code
00485 {
00486     wxString strResult(wxT("Error"));
00487     int      nReference = LUA_NOREF;
00488 
00489     EnterLuaCriticalSection();
00490     {
00491         lua_State* L = m_wxlState.GetLuaState();
00492 
00493         if (wxStrpbrk(strExpr.c_str(), wxT(" ~=<>+-*/%(){}[]:;,.\"'")) != NULL)
00494         {
00495             // an expression
00496             int nOldTop = lua_gettop(L);
00497 
00498             wxLuaCharBuffer charbuf(strExpr);
00499             int nResult = luaL_loadbuffer(L, charbuf.GetData(), charbuf.Length(), "debug");
00500 
00501             if (nResult == 0)
00502                 nResult = lua_pcall(L, 0, LUA_MULTRET, 0);  // call main
00503 
00504             if (nResult != 0)
00505                 wxlua_pushwxString(L, wxlua_LUA_ERR_msg(nResult));
00506 
00507             else if (lua_gettop(L) == nOldTop)
00508                 lua_pushliteral(L, "OK");
00509 
00510             nReference = m_wxlState.wxluaR_Ref(-1, &wxlua_lreg_refs_key);
00511             lua_settop(L, nOldTop); // throw out all return values
00512         }
00513         else
00514         {
00515              lua_Debug ar = INIT_LUA_DEBUG;
00516              int       iLevel = 0;
00517              bool      fFound = false;
00518 
00519              while (lua_getstack(L, iLevel++, &ar) != 0)
00520              {
00521                 int       iIndex = 0;
00522                 wxString name = lua2wx(lua_getlocal(L, &ar, ++iIndex));
00523                 if (!name.IsEmpty())
00524                 {
00525                     if (strExpr == name)
00526                     {
00527                         nReference = m_wxlState.wxluaR_Ref(-1, &wxlua_lreg_refs_key);
00528                         fFound = true;
00529                         break;
00530                     }
00531 
00532                     lua_pop(L, 1);
00533                 }
00534 
00535                 if (fFound)
00536                     break;
00537 
00538                 name = lua2wx(lua_getlocal(L, &ar, ++iIndex));
00539              }
00540 
00541              if (!fFound)
00542              {
00543                   int nOldTop = lua_gettop(L);
00544                   lua_pushvalue(L, LUA_GLOBALSINDEX);
00545                   lua_pushnil(L);
00546                   while (lua_next(L, -2) != 0)
00547                   {
00548                       if (lua_type(L, -2) == LUA_TSTRING)
00549                       {
00550                           wxString name = lua2wx(lua_tostring(L, -2));
00551                           if (strExpr == name)
00552                           {
00553                               nReference = m_wxlState.wxluaR_Ref(-1, &wxlua_lreg_refs_key); // reference value
00554                               lua_pop(L, 2);    // pop key and value
00555                               fFound = true;
00556                               break;
00557                           }
00558                       }
00559 
00560                       lua_pop(L, 1);  // removes `value';
00561                   }
00562                   lua_settop(L, nOldTop); // the table of globals.
00563              }
00564         }
00565 
00566         if (m_wxlState.wxluaR_GetRef(nReference, &wxlua_lreg_refs_key))
00567         {
00568             m_wxlState.wxluaR_Unref(nReference, &wxlua_lreg_refs_key);
00569 
00570             int wxl_type = 0;
00571             wxString value;
00572             wxLuaDebugData::GetTypeValue(m_wxlState, -1, &wxl_type, value);
00573 
00574             strResult = wxluaT_typename(L, wxl_type) + wxT(" : ") + value;
00575 
00576             lua_pop(L, 1);
00577         }
00578     }
00579     LeaveLuaCriticalSection();
00580 
00581     return NotifyEvaluateExpr(exprRef, strResult);
00582 }
00583 
00584 bool wxLuaDebugTarget::NotifyBreak(const wxString &fileName, int lineNumber)
00585 {
00586     return IsConnected() && !m_resetRequested &&
00587            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_BREAK) &&
00588            m_clientSocket.WriteString(fileName) &&
00589            m_clientSocket.WriteInt32(lineNumber);
00590 }
00591 
00592 bool wxLuaDebugTarget::NotifyPrint(const wxString &errorMsg)
00593 {
00594     return IsConnected() &&
00595            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_PRINT) &&
00596            m_clientSocket.WriteString(errorMsg);
00597 }
00598 
00599 bool wxLuaDebugTarget::NotifyError(const wxString &errorMsg)
00600 {
00601     if (IsConnected() &&
00602         m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_ERROR) &&
00603         m_clientSocket.WriteString(errorMsg))
00604     {
00605         return true;
00606     }
00607     else
00608         wxMessageBox(errorMsg, wxT("wxLua debug client error"), wxOK | wxCENTRE, NULL);
00609 
00610     m_fErrorsSeen = true;
00611     return false;
00612 }
00613 
00614 bool wxLuaDebugTarget::NotifyExit()
00615 {
00616     bool ret = IsConnected() &&
00617            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_EXIT);
00618 
00619     return ret;
00620 }
00621 
00622 bool wxLuaDebugTarget::NotifyStackEnumeration(const wxLuaDebugData& debugData)
00623 {
00624     return IsConnected() &&
00625            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_STACK_ENUM) &&
00626            m_clientSocket.WriteDebugData(debugData);
00627 }
00628 
00629 bool wxLuaDebugTarget::NotifyStackEntryEnumeration(int entryRef,
00630                                                    const wxLuaDebugData& debugData)
00631 {
00632     return IsConnected() &&
00633            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_STACK_ENTRY_ENUM) &&
00634            m_clientSocket.WriteInt32(entryRef) &&
00635            m_clientSocket.WriteDebugData(debugData);
00636 }
00637 
00638 bool wxLuaDebugTarget::NotifyTableEnumeration(long itemNode,
00639                                               const wxLuaDebugData& debugData)
00640 {
00641     return IsConnected() &&
00642            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_TABLE_ENUM) &&
00643            m_clientSocket.WriteLong(itemNode) &&
00644            m_clientSocket.WriteDebugData(debugData);
00645 }
00646 
00647 bool wxLuaDebugTarget::NotifyEvaluateExpr(int exprRef,
00648                                           const wxString &strResult)
00649 {
00650     return IsConnected() &&
00651            m_clientSocket.WriteCmd(wxLUASOCKET_DEBUGGEE_EVENT_EVALUATE_EXPR) &&
00652            m_clientSocket.WriteInt32(exprRef) &&
00653            m_clientSocket.WriteString(strResult);
00654 }
00655 
00656 bool wxLuaDebugTarget::DebugHook(int event)
00657 {
00658     bool fWait = false;
00659     m_fStopped = true;
00660 
00661     int      lineNumber = 0;
00662     wxString fileName;
00663 
00664     if (!(m_forceBreak && m_resetRequested))
00665     {
00666         lua_Debug luaDebug = INIT_LUA_DEBUG;
00667         lua_getstack(m_wxlState.GetLuaState(), 0, &luaDebug);
00668         lua_getinfo(m_wxlState.GetLuaState(), "Sln", &luaDebug);
00669         lineNumber = luaDebug.currentline - 1;
00670         fileName = lua2wx(luaDebug.source);
00671     }
00672 
00673     if (m_forceBreak)
00674     {
00675         if (m_resetRequested)
00676         {
00677             fWait = true;
00678             m_fExiting = true;
00679             wxExit();
00680         }
00681 
00682         if (!m_fExiting)
00683         {
00684             if (NotifyBreak(fileName, lineNumber))
00685                 fWait = true;
00686         }
00687     }
00688     else
00689     {
00690         if (event == LUA_HOOKCALL) // call
00691             m_nFramesUntilBreak++;
00692         else if ((event == LUA_HOOKRET) || (event == LUA_HOOKTAILRET)) // return
00693         {
00694             if (m_nFramesUntilBreak > 0)
00695                 m_nFramesUntilBreak--;
00696         }
00697         else if (event == LUA_HOOKLINE) // line
00698         {
00699             switch (m_nextOperation)
00700             {
00701                 case DEBUG_STEP:
00702                 {
00703                     if (NotifyBreak(fileName, lineNumber))
00704                         fWait = true;
00705 
00706                     break;
00707                 }
00708                 case DEBUG_STEPOVER:
00709                 {
00710                     if ((m_nFramesUntilBreak == 0) && NotifyBreak(fileName, lineNumber))
00711                         fWait = true;
00712 
00713                     break;
00714                 }
00715                 case DEBUG_GO:
00716                 default:
00717                 {
00718                     if (AtBreakPoint(fileName, lineNumber) && NotifyBreak(fileName, lineNumber))
00719                         fWait = true;
00720 
00721                     break;
00722                 }
00723             }
00724         }
00725     }
00726 
00727     if (fWait)
00728     {
00729         // release the critical section so
00730         // the other thread can access LUA
00731         LeaveLuaCriticalSection();
00732         // Wait for a command
00733         m_debugCondition.Wait();
00734         // acquire the critical section again
00735         EnterLuaCriticalSection();
00736     }
00737 
00738     m_fStopped = false;
00739     return fWait;
00740 }
00741 
00742 // --------------------------------------------------------------------------
00743 
00744 wxLuaDebugTarget* wxLuaDebugTarget::GetDebugTarget(lua_State* L)
00745 {
00746     wxLuaDebugTarget *pTarget = NULL;
00747 
00748     // try to get the state we've stored
00749     lua_pushstring( L, "__wxLuaDebugTarget__" );
00750     lua_rawget( L, LUA_REGISTRYINDEX );
00751     // if nothing was returned or it wasn't a ptr, abort
00752     if ( lua_islightuserdata(L, -1) )
00753         pTarget = (wxLuaDebugTarget*)lua_touserdata( L, -1 );
00754 
00755     lua_pop(L, 1);
00756 
00757     return pTarget;
00758 }
00759 
00760 void LUACALL wxLuaDebugTarget::LuaDebugHook(lua_State *L, lua_Debug *pLuaDebug)
00761 {
00762     wxLuaDebugTarget *pTarget = GetDebugTarget(L);
00763 
00764     if (pTarget != NULL)
00765         pTarget->DebugHook(pLuaDebug->event);
00766 }
00767 
00768 int LUACALL wxLuaDebugTarget::LuaPrint(lua_State *L)
00769 {
00770     int         idx;
00771     wxString stream;
00772     int n = lua_gettop(L);  /* number of arguments */
00773     lua_getglobal(L, "tostring");
00774     for (idx = 1; idx <= n;  idx++)
00775     {
00776         lua_pushvalue(L, -1);  /* function to be called */
00777         lua_pushvalue(L, idx);   /* value to print */
00778         lua_call(L, 1, 1);
00779         wxString s = lua2wx(lua_tostring(L, -1));  /* get result */
00780         if (s.IsEmpty())
00781             return luaL_error(L, "`tostring' must return a string to `print'");
00782         if (idx > 1)
00783             stream.Append(wxT("\t"));
00784         stream.Append(s);
00785         lua_pop(L, 1);  /* pop result */
00786     }
00787 
00788     wxLuaDebugTarget *pTarget = GetDebugTarget(L);
00789 
00790     if (pTarget != NULL)
00791         pTarget->NotifyPrint(stream);
00792 
00793     return 0;
00794 }
Generated on Tue Jul 13 10:30:39 2010 for wxLua by  doxygen 1.6.3