1 /*
2 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3 * http://www.gnu.org/licenses/gpl-3.0.html
4 *
5 * $Revision: 11830 $
6 * $Id: debuggerdriver.cpp 11830 2019-08-28 22:59:36Z pecanh $
7 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/plugins/debuggergdb/debuggerdriver.cpp $
8 */
9
10 #include <sdk.h>
11 #include "debuggerdriver.h"
12 #include "debuggergdb.h"
13 #include "macrosmanager.h"
14
15 #include <cbdebugger_interfaces.h>
16
DebuggerDriver(DebuggerGDB * plugin)17 DebuggerDriver::DebuggerDriver(DebuggerGDB* plugin)
18 : m_pDBG(plugin),
19 m_ProgramIsStopped(true),
20 m_ChildPID(0),
21 m_QueueBusy(false),
22 m_currentFrameNo(0),
23 m_userSelectedFrameNo(-1)
24 {
25 //ctor
26 }
27
~DebuggerDriver()28 DebuggerDriver::~DebuggerDriver()
29 {
30 //dtor
31 for (size_t ii = 0; ii < m_DCmds.GetCount(); ++ii)
32 delete m_DCmds[ii];
33 m_DCmds.Clear();
34 }
35
Log(const wxString & msg)36 void DebuggerDriver::Log(const wxString& msg)
37 {
38 m_pDBG->Log(msg);
39 }
40
DebugLog(const wxString & msg)41 void DebuggerDriver::DebugLog(const wxString& msg)
42 {
43 m_pDBG->DebugLog(msg);
44 }
45
ClearDirectories()46 void DebuggerDriver::ClearDirectories()
47 {
48 m_Dirs.Clear();
49 }
50
AddDirectory(const wxString & dir)51 void DebuggerDriver::AddDirectory(const wxString& dir)
52 {
53 if (m_Dirs.Index(dir) == wxNOT_FOUND)
54 m_Dirs.Add(dir);
55 }
56
SetWorkingDirectory(const wxString & dir)57 void DebuggerDriver::SetWorkingDirectory(const wxString& dir)
58 {
59 m_WorkingDir = dir;
60 }
61
GetDebuggersWorkingDirectory() const62 wxString DebuggerDriver::GetDebuggersWorkingDirectory() const
63 {
64 if (m_WorkingDir.empty())
65 return wxEmptyString;
66 wxString oldDir = wxGetCwd();
67 wxSetWorkingDirectory(m_WorkingDir);
68 wxString newDir = wxGetCwd();
69 wxSetWorkingDirectory(oldDir);
70 return newDir;
71 }
72
SetArguments(const wxString & args)73 void DebuggerDriver::SetArguments(const wxString& args)
74 {
75 m_Args = args;
76 Manager::Get()->GetMacrosManager()->ReplaceMacros(m_Args);
77 }
78
ShowFile(const wxString & file,int line)79 void DebuggerDriver::ShowFile(const wxString& file, int line)
80 {
81 wxCommandEvent event(DEBUGGER_SHOW_FILE_LINE);
82 event.SetString(file);
83 event.SetInt(line);
84 m_pDBG->ProcessEvent(event);
85 }
86
NotifyCursorChanged()87 void DebuggerDriver::NotifyCursorChanged()
88 {
89 if (!m_Cursor.changed || m_LastCursorAddress == m_Cursor.address)
90 return;
91 m_LastCursorAddress = m_Cursor.address;
92 wxCommandEvent event(DEBUGGER_CURSOR_CHANGED);
93 m_pDBG->ProcessEvent(event);
94 }
95
NotifyDebuggeeContinued()96 void DebuggerDriver::NotifyDebuggeeContinued()
97 {
98 m_pDBG->DebuggeeContinued();
99 ResetCursor();
100 }
101
ResetCursor()102 void DebuggerDriver::ResetCursor()
103 {
104 m_LastCursorAddress.Clear();
105 m_Cursor.address.Clear();
106 m_Cursor.file.Clear();
107 m_Cursor.function.Clear();
108 m_Cursor.line = -1;
109 m_Cursor.changed = false;
110 }
111
QueueCommand(DebuggerCmd * dcmd,QueuePriority prio)112 void DebuggerDriver::QueueCommand(DebuggerCmd* dcmd, QueuePriority prio)
113 {
114 // DebugLog(_T("Queueing command: ") + dcmd->m_Cmd);
115 if (prio == Low)
116 m_DCmds.Add(dcmd);
117 else
118 m_DCmds.Insert(dcmd, 0);
119 RunQueue();
120 }
121
CurrentCommand()122 DebuggerCmd* DebuggerDriver::CurrentCommand()
123 {
124 return m_DCmds.GetCount() ? m_DCmds[0] : 0;
125 }
126
RunQueue()127 void DebuggerDriver::RunQueue()
128 {
129 if (m_QueueBusy || !m_DCmds.GetCount() || !IsProgramStopped())
130 return;
131
132 DebuggerCmd *command = CurrentCommand();
133
134 // Log(_T("Running command: ") + CurrentCommand()->m_Cmd);
135 // don't send a command if empty; most debuggers repeat the last command this way...
136 if (!command->m_Cmd.IsEmpty())
137 {
138 m_QueueBusy = true;
139 m_pDBG->DoSendCommand(command->m_Cmd);
140 if (command->IsContinueCommand())
141 m_ProgramIsStopped = false;
142 }
143
144 // Call Action()
145 command->Action();
146
147 // If the command was an action (i.e. no command specified,
148 // remove it from the queue and run the next command.
149 // For other commands, this happens in driver's ParseOutput().
150 if (command->m_Cmd.IsEmpty())
151 {
152 RemoveTopCommand(true);
153 RunQueue();
154 }
155 }
156
RemoveTopCommand(bool deleteIt)157 void DebuggerDriver::RemoveTopCommand(bool deleteIt)
158 {
159 if (m_QueueBusy || !m_DCmds.GetCount())
160 return;
161
162 // Log(_T("Removing command: ") + CurrentCommand()->m_Cmd);
163 if (deleteIt)
164 delete m_DCmds[0];
165 m_DCmds.RemoveAt(0);
166 }
167
GetStackFrames() const168 DebuggerDriver::StackFrameContainer const & DebuggerDriver::GetStackFrames() const
169 {
170 return m_backtrace;
171 }
172
GetStackFrames()173 DebuggerDriver::StackFrameContainer& DebuggerDriver::GetStackFrames()
174 {
175 return m_backtrace;
176 }
177
GetThreads() const178 const DebuggerDriver::ThreadsContainer & DebuggerDriver::GetThreads() const
179 {
180 return m_threads;
181 }
182
GetThreads()183 DebuggerDriver::ThreadsContainer & DebuggerDriver::GetThreads()
184 {
185 return m_threads;
186 }
187
SetCurrentFrame(int number,bool user_selected)188 void DebuggerDriver::SetCurrentFrame(int number, bool user_selected)
189 {
190 m_currentFrameNo = number;
191 if (user_selected)
192 m_userSelectedFrameNo = number;
193 }
194
ResetCurrentFrame()195 void DebuggerDriver::ResetCurrentFrame()
196 {
197 m_currentFrameNo = 0;
198 m_userSelectedFrameNo = -1;
199
200 if (Manager::Get()->GetDebuggerManager()->UpdateBacktrace())
201 Manager::Get()->GetDebuggerManager()->GetBacktraceDialog()->Reload();
202 }
203
204