00001
00002
00003
00004
00005
00006
00007
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
00031
00032
00033 void *wxLuaDebugTarget::LuaThread::Entry()
00034 {
00035 m_pTarget->ThreadFunction();
00036
00037 return 0;
00038 }
00039
00040
00041
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
00066 lua_pushstring( L, "__wxLuaDebugTarget__" );
00067 lua_pushlightuserdata( L, (void*)this );
00068
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
00082
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
00106 m_fErrorsSeen = true;
00107
00108 m_pThread = new LuaThread(this);
00109
00110 if ((m_pThread != NULL) &&
00111 (m_pThread->Create() == wxTHREAD_NO_ERROR) &&
00112 (m_pThread->Run() == wxTHREAD_NO_ERROR))
00113 {
00114
00115 if (!IsConnected())
00116 {
00117 wxMessageBox(wxT("Unable to connect to server"), wxT("wxLua client"), wxOK | wxCENTRE, NULL);
00118 }
00119 else
00120 {
00121
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;
00180 }
00181
00182 while (fThreadRunning && !m_pThread->TestDestroy() && !m_resetRequested && !m_fExiting)
00183 {
00184 unsigned char debugCommand = 0;
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
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:
00330 ret = true;
00331 break;
00332 case wxLUASOCKET_DEBUGGER_CMD_ENABLE_BREAKPOINT:
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)
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
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);
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);
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);
00554 lua_pop(L, 2);
00555 fFound = true;
00556 break;
00557 }
00558 }
00559
00560 lua_pop(L, 1);
00561 }
00562 lua_settop(L, nOldTop);
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)
00691 m_nFramesUntilBreak++;
00692 else if ((event == LUA_HOOKRET) || (event == LUA_HOOKTAILRET))
00693 {
00694 if (m_nFramesUntilBreak > 0)
00695 m_nFramesUntilBreak--;
00696 }
00697 else if (event == LUA_HOOKLINE)
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
00730
00731 LeaveLuaCriticalSection();
00732
00733 m_debugCondition.Wait();
00734
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
00749 lua_pushstring( L, "__wxLuaDebugTarget__" );
00750 lua_rawget( L, LUA_REGISTRYINDEX );
00751
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);
00773 lua_getglobal(L, "tostring");
00774 for (idx = 1; idx <= n; idx++)
00775 {
00776 lua_pushvalue(L, -1);
00777 lua_pushvalue(L, idx);
00778 lua_call(L, 1, 1);
00779 wxString s = lua2wx(lua_tostring(L, -1));
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);
00786 }
00787
00788 wxLuaDebugTarget *pTarget = GetDebugTarget(L);
00789
00790 if (pTarget != NULL)
00791 pTarget->NotifyPrint(stream);
00792
00793 return 0;
00794 }