Implementing and Calling Bind
In a typical situation, all bound breakpoints would be retained in a list, probably in each Program object, where they would be associated with particular threads for easy searching. Then, when the debug engine detects that a bound breakpoint has been hit, it would use that exact breakpoint to send a breakpoint event to the SDM.
In the TextInterpreter project, the text of a loaded file is never actually interpreted (unlike a real program interpreter) so "encountering a breakpoint" doesn't really happen. Instead, after the program object has been created and the load and entry point events have been sent, the TextInterpreter immediately sends the breakpoint event, using the last bound breakpoint, thus simulating an actual breakpoint being encountered. This means that only one breakpoint will be encountered (the last one), regardless of the number of breakpoints set. Then, when the text program is "continued," the program exits. Saving the last bound breakpoint in a global variable is a simple convenience for TextInterpreter.
To implement the Bind method
In Class View, right-click the CPendingBreakpoint class, click Add Variable, and add a variable with the Variable name m_sbstrDoc, a Variable type of CComBSTR, and an Access type of protected.
Add another variable to CPendingBreakpoint class, this one with the Variable name m_posBeg, a Variable type of TEXT_POSITION, and an Access type of protected.
Open the Breakpoint.cpp file and insert the following bold line after the last #include:
#include "EventBase.h" #include "Context.h"
Immediately after the line added in step 3, add the following bold lines:
#include "Context.h" // Last breakpoint that was bound CComObject<CBoundBreakpoint> *gpBP;
In Breakpoint.cpp, find CPendingBreakpoint::Bind and replace the line //TODO: IMPLEMENT BIND as well as the following return statement with the following:
BP_REQUEST_INFO bpRequestInfo; m_spBPRequest->GetRequestInfo(BPREQI_ALLFIELDS, &bpRequestInfo); if (bpRequestInfo.dwFields & BPREQI_BPLOCATION && bpRequestInfo.bpLocation.bpLocationType == BPLT_CODE_FILE_LINE) { // Get the file name of the document. bpRequestInfo.bpLocation.bpLocation.bplocCodeFileLine.pDocPos-> GetFileName(&m_sbstrDoc); // Get the position in the document bpRequestInfo.bpLocation.bpLocation.bplocCodeFileLine.pDocPos-> GetRange(&m_posBeg, NULL); // Create a context CComObject<CDebugContext>* pContext; CComObject<CDebugContext>::CreateInstance(&pContext); pContext->AddRef(); pContext->Initialize(m_sbstrDoc, m_posBeg); // Create a breakpoint resolution CComObject<CBreakpointResolution>* pBPRes; CComObject<CBreakpointResolution>::CreateInstance(&pBPRes); pBPRes->AddRef(); pBPRes->Initialize(pContext); // Create a bound breakpoint CComObject<CBoundBreakpoint>* pBoundBP; CComObject<CBoundBreakpoint>::CreateInstance(&pBoundBP); pBoundBP->AddRef(); pBoundBP->Initialize(this, pBPRes); SendBoundEvent(pBoundBP); // Save the last bound event. if (gpBP) gpBP->Release(); gpBP = pBoundBP; gpBP->AddRef(); pBoundBP->Release(); pBPRes->Release(); pContext->Release(); return S_OK; } return E_NOTIMPL;
Open the Breakpoint.h file and insert the following bold line at the end of the file:
OBJECT_ENTRY_AUTO(__uuidof(BoundBreakpoint), CBoundBreakpoint) extern CComObject<CBoundBreakpoint> *gpBP;
Open the Program.h file, and insert the following bold line after the last #include:
#include "TextInterpreter.h" #include "Breakpoint.h"
In Program.h, find the FinalConstruct method for the CProgram class and insert the following bold line:
HRESULT FinalConstruct() { gpBP = NULL; return S_OK; }
Also in Program.h, find the FinalRelease method in the CProgram class and add the following bold lines:
void FinalRelease() { if (gpBP) gpBP->Release(); }
Build the project to make sure there are no errors.