File: | tools/lldb/tools/lldb-mi/MIDriver.cpp |
Location: | line 697, column 9 |
Description: | Value stored to 'bHaveInput' is never read |
1 | //===-- MIDriver.cpp --------------------------------------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | //++ |
11 | // File: MIDriver.cpp |
12 | // |
13 | // Overview: CMIDriver implementation. |
14 | // |
15 | // Environment: Compilers: Visual C++ 12. |
16 | // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 |
17 | // Libraries: See MIReadmetxt. |
18 | // |
19 | // Copyright: None. |
20 | //-- |
21 | |
22 | // Third party headers: |
23 | #include <stdarg.h> // va_list, va_start, var_end |
24 | #include <iostream> |
25 | #include "lldb/API/SBError.h" |
26 | |
27 | // In-house headers: |
28 | #include "Driver.h" |
29 | #include "MIDriver.h" |
30 | #include "MICmnResources.h" |
31 | #include "MICmnLog.h" |
32 | #include "MICmdMgr.h" |
33 | #include "MICmnLLDBDebugger.h" |
34 | #include "MICmnMIResultRecord.h" |
35 | #include "MICmnMIValueConst.h" |
36 | #include "MICmnThreadMgrStd.h" |
37 | #include "MIUtilDebug.h" |
38 | #include "MIUtilSingletonHelper.h" |
39 | #include "MICmnStreamStdout.h" |
40 | #include "MICmnStreamStderr.h" |
41 | #include "MICmdArgValFile.h" |
42 | #include "MICmdArgValString.h" |
43 | #include "MICmnConfig.h" |
44 | |
45 | // Instantiations: |
46 | #if _DEBUG1 |
47 | const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC(IDS_MI_VERSION_DESCRIPTION_DEBUG)CMICmnResources::Instance().GetString(IDS_MI_VERSION_DESCRIPTION_DEBUG ).c_str(); |
48 | #else |
49 | const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC(IDS_MI_VERSION_DESCRIPTION)CMICmnResources::Instance().GetString(IDS_MI_VERSION_DESCRIPTION ).c_str(); // Matches version in resources file |
50 | #endif // _DEBUG |
51 | const CMIUtilString CMIDriver::ms_constAppNameShort(MIRSRC(IDS_MI_APPNAME_SHORT)CMICmnResources::Instance().GetString(IDS_MI_APPNAME_SHORT).c_str ()); |
52 | const CMIUtilString CMIDriver::ms_constAppNameLong(MIRSRC(IDS_MI_APPNAME_LONG)CMICmnResources::Instance().GetString(IDS_MI_APPNAME_LONG).c_str ()); |
53 | |
54 | //++ ------------------------------------------------------------------------------------ |
55 | // Details: CMIDriver constructor. |
56 | // Type: Method. |
57 | // Args: None. |
58 | // Return: None. |
59 | // Throws: None. |
60 | //-- |
61 | CMIDriver::CMIDriver(void) |
62 | : m_bFallThruToOtherDriverEnabled(false) |
63 | , m_bDriverIsExiting(false) |
64 | , m_handleMainThread(0) |
65 | , m_rStdin(CMICmnStreamStdin::Instance()) |
66 | , m_rLldbDebugger(CMICmnLLDBDebugger::Instance()) |
67 | , m_rStdOut(CMICmnStreamStdout::Instance()) |
68 | , m_eCurrentDriverState(eDriverState_NotRunning) |
69 | , m_bHaveExecutableFileNamePathOnCmdLine(false) |
70 | , m_bDriverDebuggingArgExecutable(false) |
71 | { |
72 | } |
73 | |
74 | //++ ------------------------------------------------------------------------------------ |
75 | // Details: CMIDriver destructor. |
76 | // Type: Overridden. |
77 | // Args: None. |
78 | // Return: None. |
79 | // Throws: None. |
80 | //-- |
81 | CMIDriver::~CMIDriver(void) |
82 | { |
83 | } |
84 | |
85 | //++ ------------------------------------------------------------------------------------ |
86 | // Details: Set whether *this driver (the parent) is enabled to pass a command to its |
87 | // fall through (child) driver to interpret the command and do work instead |
88 | // (if *this driver decides it can't hanled the command). |
89 | // Type: Method. |
90 | // Args: vbYes - (R) True = yes fall through, false = do not pass on command. |
91 | // Return: MIstatus::success - Functional succeeded. |
92 | // MIstatus::failure - Functional failed. |
93 | // Throws: None. |
94 | //-- |
95 | bool |
96 | CMIDriver::SetEnableFallThru(const bool vbYes) |
97 | { |
98 | m_bFallThruToOtherDriverEnabled = vbYes; |
99 | return MIstatus::success; |
100 | } |
101 | |
102 | //++ ------------------------------------------------------------------------------------ |
103 | // Details: Get whether *this driver (the parent) is enabled to pass a command to its |
104 | // fall through (child) driver to interpret the command and do work instead |
105 | // (if *this driver decides it can't hanled the command). |
106 | // Type: Method. |
107 | // Args: None. |
108 | // Return: bool - True = yes fall through, false = do not pass on command. |
109 | // Throws: None. |
110 | //-- |
111 | bool |
112 | CMIDriver::GetEnableFallThru(void) const |
113 | { |
114 | return m_bFallThruToOtherDriverEnabled; |
115 | } |
116 | |
117 | //++ ------------------------------------------------------------------------------------ |
118 | // Details: Retrieve MI's application name of itself. |
119 | // Type: Method. |
120 | // Args: None. |
121 | // Return: CMIUtilString & - Text description. |
122 | // Throws: None. |
123 | //-- |
124 | const CMIUtilString & |
125 | CMIDriver::GetAppNameShort(void) const |
126 | { |
127 | return ms_constAppNameShort; |
128 | } |
129 | |
130 | //++ ------------------------------------------------------------------------------------ |
131 | // Details: Retrieve MI's application name of itself. |
132 | // Type: Method. |
133 | // Args: None. |
134 | // Return: CMIUtilString & - Text description. |
135 | // Throws: None. |
136 | //-- |
137 | const CMIUtilString & |
138 | CMIDriver::GetAppNameLong(void) const |
139 | { |
140 | return ms_constAppNameLong; |
141 | } |
142 | |
143 | //++ ------------------------------------------------------------------------------------ |
144 | // Details: Retrieve MI's version description of itself. |
145 | // Type: Method. |
146 | // Args: None. |
147 | // Return: CMIUtilString & - Text description. |
148 | // Throws: None. |
149 | //-- |
150 | const CMIUtilString & |
151 | CMIDriver::GetVersionDescription(void) const |
152 | { |
153 | return ms_constMIVersion; |
154 | } |
155 | |
156 | //++ ------------------------------------------------------------------------------------ |
157 | // Details: Initialize setup *this driver ready for use. |
158 | // Type: Method. |
159 | // Args: None. |
160 | // Return: MIstatus::success - Functional succeeded. |
161 | // MIstatus::failure - Functional failed. |
162 | // Throws: None. |
163 | //-- |
164 | bool |
165 | CMIDriver::Initialize(void) |
166 | { |
167 | m_eCurrentDriverState = eDriverState_Initialising; |
168 | m_clientUsageRefCnt++; |
169 | |
170 | ClrErrorDescription(); |
171 | |
172 | if (m_bInitialized) |
173 | return MIstatus::success; |
174 | |
175 | bool bOk = MIstatus::success; |
176 | CMIUtilString errMsg; |
177 | |
178 | // Initialize all of the modules we depend on |
179 | MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); |
180 | MI::ModuleInit<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); |
181 | MI::ModuleInit<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); |
182 | MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); |
183 | MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); |
184 | MI::ModuleInit<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); |
185 | MI::ModuleInit<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); |
186 | bOk &= m_rLldbDebugger.SetDriver(*this); |
187 | MI::ModuleInit<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); |
188 | |
189 | #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER1 |
190 | CMIDriverMgr &rDrvMgr = CMIDriverMgr::Instance(); |
191 | bOk = bOk && rDrvMgr.RegisterDriver(*g_driver, "LLDB driver"); // Will be pass thru driver |
192 | if (bOk) |
193 | { |
194 | bOk = SetEnableFallThru(false); // This is intentional at this time - yet to be fully implemented |
195 | bOk = bOk && SetDriverToFallThruTo(*g_driver); |
196 | CMIUtilString strOtherDrvErrMsg; |
197 | if (bOk && GetEnableFallThru() && !g_driver->MISetup(strOtherDrvErrMsg)) |
198 | { |
199 | bOk = false; |
200 | errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_FALLTHRUDRIVER)CMICmnResources::Instance().GetString(IDS_MI_INIT_ERR_FALLTHRUDRIVER ).c_str(), strOtherDrvErrMsg.c_str()); |
201 | } |
202 | } |
203 | #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER |
204 | |
205 | m_bExitApp = false; |
206 | |
207 | m_bInitialized = bOk; |
208 | |
209 | if (!bOk) |
210 | { |
211 | const CMIUtilString msg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVER)CMICmnResources::Instance().GetString(IDS_MI_INIT_ERR_DRIVER) .c_str(), errMsg.c_str()); |
212 | SetErrorDescription(msg); |
213 | return MIstatus::failure; |
214 | } |
215 | |
216 | m_eCurrentDriverState = eDriverState_RunningNotDebugging; |
217 | |
218 | return bOk; |
219 | } |
220 | |
221 | //++ ------------------------------------------------------------------------------------ |
222 | // Details: Unbind detach or release resources used by *this driver. |
223 | // Type: Method. |
224 | // Args: None. |
225 | // Return: MIstatus::success - Functional succeeded. |
226 | // MIstatus::failure - Functional failed. |
227 | // Throws: None. |
228 | //-- |
229 | bool |
230 | CMIDriver::Shutdown(void) |
231 | { |
232 | if (--m_clientUsageRefCnt > 0) |
233 | return MIstatus::success; |
234 | |
235 | if (!m_bInitialized) |
236 | return MIstatus::success; |
237 | |
238 | m_eCurrentDriverState = eDriverState_ShuttingDown; |
239 | |
240 | ClrErrorDescription(); |
241 | |
242 | bool bOk = MIstatus::success; |
243 | CMIUtilString errMsg; |
244 | |
245 | // Shutdown all of the modules we depend on |
246 | MI::ModuleShutdown<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); |
247 | MI::ModuleShutdown<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); |
248 | MI::ModuleShutdown<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); |
249 | MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); |
250 | MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); |
251 | MI::ModuleShutdown<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); |
252 | MI::ModuleShutdown<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); |
253 | MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); |
254 | |
255 | if (!bOk) |
256 | { |
257 | SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR)CMICmnResources::Instance().GetString(IDS_MI_SHUTDOWN_ERR).c_str (), errMsg.c_str()); |
258 | } |
259 | |
260 | m_eCurrentDriverState = eDriverState_NotRunning; |
261 | |
262 | return bOk; |
263 | } |
264 | |
265 | //++ ------------------------------------------------------------------------------------ |
266 | // Details: Work function. Client (the driver's user) is able to append their own message |
267 | // in to the MI's Log trace file. |
268 | // Type: Method. |
269 | // Args: vMessage - (R) Client's text message. |
270 | // Return: MIstatus::success - Functional succeeded. |
271 | // MIstatus::failure - Functional failed. |
272 | // Throws: None. |
273 | //-- |
274 | bool |
275 | CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage) |
276 | { |
277 | CMIUtilString msg; |
278 | msg = CMIUtilString::Format(MIRSRC(IDS_MI_CLIENT_MSG)CMICmnResources::Instance().GetString(IDS_MI_CLIENT_MSG).c_str (), vMessage.c_str()); |
279 | return m_pLog->Write(msg, CMICmnLog::eLogVerbosity_ClientMsg); |
280 | } |
281 | |
282 | //++ ------------------------------------------------------------------------------------ |
283 | // Details: CDriverMgr calls *this driver initialize setup ready for use. |
284 | // Type: Overridden. |
285 | // Args: None. |
286 | // Return: MIstatus::success - Functional succeeded. |
287 | // MIstatus::failure - Functional failed. |
288 | // Throws: None. |
289 | //-- |
290 | bool |
291 | CMIDriver::DoInitialize(void) |
292 | { |
293 | return CMIDriver::Instance().Initialize(); |
294 | } |
295 | |
296 | //++ ------------------------------------------------------------------------------------ |
297 | // Details: CDriverMgr calls *this driver to unbind detach or release resources used by |
298 | // *this driver. |
299 | // Type: Overridden. |
300 | // Args: None. |
301 | // Return: MIstatus::success - Functional succeeded. |
302 | // MIstatus::failure - Functional failed. |
303 | // Throws: None. |
304 | //-- |
305 | bool |
306 | CMIDriver::DoShutdown(void) |
307 | { |
308 | return CMIDriver::Instance().Shutdown(); |
309 | } |
310 | |
311 | //++ ------------------------------------------------------------------------------------ |
312 | // Details: Retrieve the name for *this driver. |
313 | // Type: Overridden. |
314 | // Args: None. |
315 | // Return: CMIUtilString & - Driver name. |
316 | // Throws: None. |
317 | //-- |
318 | const CMIUtilString & |
319 | CMIDriver::GetName(void) const |
320 | { |
321 | const CMIUtilString &rName = GetAppNameLong(); |
322 | const CMIUtilString &rVsn = GetVersionDescription(); |
323 | static CMIUtilString strName = CMIUtilString::Format("%s %s", rName.c_str(), rVsn.c_str()); |
324 | |
325 | return strName; |
326 | } |
327 | |
328 | //++ ------------------------------------------------------------------------------------ |
329 | // Details: Retrieve *this driver's last error condition. |
330 | // Type: Overridden. |
331 | // Args: None. |
332 | // Return: CMIUtilString - Text description. |
333 | // Throws: None. |
334 | //-- |
335 | CMIUtilString |
336 | CMIDriver::GetError(void) const |
337 | { |
338 | return GetErrorDescription(); |
339 | } |
340 | |
341 | //++ ------------------------------------------------------------------------------------ |
342 | // Details: Call *this driver to resize the console window. |
343 | // Type: Overridden. |
344 | // Args: vTermWidth - (R) New window column size. |
345 | // Return: MIstatus::success - Functional succeeded. |
346 | // MIstatus::failure - Functional failed. |
347 | // Throws: None. |
348 | //-- |
349 | void |
350 | CMIDriver::DoResizeWindow(const uint32_t vTermWidth) |
351 | { |
352 | GetTheDebugger().SetTerminalWidth(vTermWidth); |
353 | } |
354 | |
355 | //++ ------------------------------------------------------------------------------------ |
356 | // Details: Call *this driver to return it's debugger. |
357 | // Type: Overridden. |
358 | // Args: None. |
359 | // Return: lldb::SBDebugger & - LLDB debugger object reference. |
360 | // Throws: None. |
361 | //-- |
362 | lldb::SBDebugger & |
363 | CMIDriver::GetTheDebugger(void) |
364 | { |
365 | return m_rLldbDebugger.GetTheDebugger(); |
366 | } |
367 | |
368 | //++ ------------------------------------------------------------------------------------ |
369 | // Details: Specify another driver *this driver can call should this driver not be able |
370 | // to handle the client data input. DoFallThruToAnotherDriver() makes the call. |
371 | // Type: Overridden. |
372 | // Args: vrOtherDriver - (R) Reference to another driver object. |
373 | // Return: MIstatus::success - Functional succeeded. |
374 | // MIstatus::failure - Functional failed. |
375 | // Throws: None. |
376 | //-- |
377 | bool |
378 | CMIDriver::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) |
379 | { |
380 | m_pDriverFallThru = const_cast<CMIDriverBase *>(&vrOtherDriver); |
381 | |
382 | return m_pDriverFallThru->SetDriverParent(*this); |
383 | } |
384 | |
385 | //++ ------------------------------------------------------------------------------------ |
386 | // Details: Proxy function CMIDriverMgr IDriver interface implementation. *this driver's |
387 | // implementation called from here to match the existing function name of the |
388 | // original LLDb driver class (the extra indirection is not necessarily required). |
389 | // Check the arguments that were passed to this program to make sure they are |
390 | // valid and to get their argument values (if any). |
391 | // Type: Overridden. |
392 | // Args: argc - (R) An integer that contains the count of arguments that follow in |
393 | // argv. The argc parameter is always greater than or equal to 1. |
394 | // argv - (R) An array of null-terminated strings representing command-line |
395 | // arguments entered by the user of the program. By convention, |
396 | // argv[0] is the command with which the program is invoked. |
397 | // vpStdOut - (R) Pointer to a standard output stream. |
398 | // vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), |
399 | // version information only. |
400 | // False = Continue to work, start debugger i.e. Command |
401 | // interpreter. |
402 | // Return: lldb::SBError - LLDB current error status. |
403 | // Throws: None. |
404 | //-- |
405 | lldb::SBError |
406 | CMIDriver::DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) |
407 | { |
408 | return ParseArgs(argc, argv, vpStdOut, vwbExiting); |
409 | } |
410 | |
411 | //++ ------------------------------------------------------------------------------------ |
412 | // Details: Check the arguments that were passed to this program to make sure they are |
413 | // valid and to get their argument values (if any). The following are options |
414 | // that are only handled by *this driver: |
415 | // --executable |
416 | // The application's options --interpreter and --executable in code act very similar. |
417 | // The --executable is necessary to differentiate whither the MI Driver is being |
418 | // using by a client i.e. Eclipse or from the command line. Eclipse issues the option |
419 | // --interpreter and also passes additional arguments which can be interpreted as an |
420 | // executable if called from the command line. Using --executable tells the MI |
421 | // Driver is being called the command line and that the executable argument is indeed |
422 | // a specified executable an so actions commands to set up the executable for a |
423 | // debug session. Using --interpreter on the commnd line does not action additional |
424 | // commands to initialise a debug session and so be able to launch the process. |
425 | // Type: Overridden. |
426 | // Args: argc - (R) An integer that contains the count of arguments that follow in |
427 | // argv. The argc parameter is always greater than or equal to 1. |
428 | // argv - (R) An array of null-terminated strings representing command-line |
429 | // arguments entered by the user of the program. By convention, |
430 | // argv[0] is the command with which the program is invoked. |
431 | // vpStdOut - (R) Pointer to a standard output stream. |
432 | // vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), |
433 | // version information only. |
434 | // False = Continue to work, start debugger i.e. Command |
435 | // interpreter. |
436 | // Return: lldb::SBError - LLDB current error status. |
437 | // Throws: None. |
438 | //-- |
439 | lldb::SBError |
440 | CMIDriver::ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) |
441 | { |
442 | lldb::SBError errStatus; |
443 | const bool bHaveArgs(argc >= 2); |
444 | |
445 | // *** Add any args handled here to GetHelpOnCmdLineArgOptions() *** |
446 | |
447 | // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING |
448 | // Look for the command line options |
449 | bool bHaveExecutableFileNamePath = false; |
450 | bool bHaveExecutableLongOption = false; |
451 | |
452 | if (bHaveArgs) |
453 | { |
454 | // Search right to left to look for the executable |
455 | for (MIint i = argc - 1; i > 0; i--) |
456 | { |
457 | const CMIUtilString strArg(argv[i]); |
458 | const CMICmdArgValFile argFile; |
459 | if (argFile.IsFilePath(strArg) || CMICmdArgValString(true, false, true).IsStringArg(strArg)) |
460 | { |
461 | bHaveExecutableFileNamePath = true; |
462 | m_strCmdLineArgExecuteableFileNamePath = argFile.GetFileNamePath(strArg); |
463 | m_bHaveExecutableFileNamePathOnCmdLine = true; |
464 | } |
465 | // This argument is also check for in CMIDriverMgr::ParseArgs() |
466 | if (0 == strArg.compare("--executable")) // Used to specify that there is executable argument also on the command line |
467 | { // See fn description. |
468 | bHaveExecutableLongOption = true; |
469 | } |
470 | } |
471 | } |
472 | |
473 | if (bHaveExecutableFileNamePath && bHaveExecutableLongOption) |
474 | { |
475 | // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION |
476 | #if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION0 |
477 | SetDriverDebuggingArgExecutable(); |
478 | #else |
479 | vwbExiting = true; |
480 | errStatus.SetErrorString(MIRSRC(IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL)CMICmnResources::Instance().GetString(IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL ).c_str()); |
481 | #endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION |
482 | } |
483 | |
484 | return errStatus; |
485 | } |
486 | |
487 | //++ ------------------------------------------------------------------------------------ |
488 | // Details: A client can ask if *this driver is GDB/MI compatible. |
489 | // Type: Overridden. |
490 | // Args: None. |
491 | // Return: True - GBD/MI compatible LLDB front end. |
492 | // False - Not GBD/MI compatible LLDB front end. |
493 | // Throws: None. |
494 | //-- |
495 | bool |
496 | CMIDriver::GetDriverIsGDBMICompatibleDriver(void) const |
497 | { |
498 | return true; |
499 | } |
500 | |
501 | //++ ------------------------------------------------------------------------------------ |
502 | // Details: Callback function for monitoring stream stdin object. Part of the visitor |
503 | // pattern. |
504 | // This function is called by the CMICmnStreamStdin::CThreadStdin |
505 | // "stdin monitor" thread (ID). |
506 | // Type: Overridden. |
507 | // Args: vStdInBuffer - (R) Copy of the current stdin line data. |
508 | // vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor. |
509 | // Return: MIstatus::success - Functional succeeded. |
510 | // MIstatus::failure - Functional failed. |
511 | // Throws: None. |
512 | //-- |
513 | bool |
514 | CMIDriver::ReadLine(const CMIUtilString &vStdInBuffer, bool &vrwbYesExit) |
515 | { |
516 | // For debugging. Update prompt show stdin is working |
517 | // printf( "%s\n", vStdInBuffer.c_str() ); |
518 | // fflush( stdout ); |
519 | |
520 | // Special case look for the quit command here so stop monitoring stdin stream |
521 | // So we do not go back to fgetc() and wait and hang thread on exit |
522 | if (vStdInBuffer == "quit") |
523 | vrwbYesExit = true; |
524 | |
525 | // 1. Put new line in the queue container by stdin monitor thread |
526 | // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its |
527 | // own thread |
528 | const bool bOk = QueueMICommand(vStdInBuffer); |
529 | |
530 | // Check to see if the *this driver is shutting down (exit application) |
531 | if (!vrwbYesExit) |
532 | vrwbYesExit = m_bDriverIsExiting; |
533 | |
534 | return bOk; |
535 | } |
536 | |
537 | //++ ------------------------------------------------------------------------------------ |
538 | // Details: Start worker threads for the driver. |
539 | // Type: Method. |
540 | // Args: None. |
541 | // Return: MIstatus::success - Functional succeeded. |
542 | // MIstatus::failure - Functional failed. |
543 | // Throws: None. |
544 | //-- |
545 | bool |
546 | CMIDriver::StartWorkerThreads(void) |
547 | { |
548 | bool bOk = MIstatus::success; |
549 | |
550 | // Grab the thread manager |
551 | CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); |
552 | |
553 | // Start the stdin thread |
554 | bOk &= m_rStdin.SetVisitor(*this); |
555 | if (bOk && !rThreadMgr.ThreadStart<CMICmnStreamStdin>(m_rStdin)) |
556 | { |
557 | const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE)CMICmnResources::Instance().GetString(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ).c_str(), |
558 | CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); |
559 | SetErrorDescriptionn(errMsg); |
560 | return MIstatus::failure; |
561 | } |
562 | |
563 | // Start the event polling thread |
564 | if (bOk && !rThreadMgr.ThreadStart<CMICmnLLDBDebugger>(m_rLldbDebugger)) |
565 | { |
566 | const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE)CMICmnResources::Instance().GetString(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ).c_str(), |
567 | CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); |
568 | SetErrorDescriptionn(errMsg); |
569 | return MIstatus::failure; |
570 | } |
571 | |
572 | return bOk; |
573 | } |
574 | |
575 | //++ ------------------------------------------------------------------------------------ |
576 | // Details: Stop worker threads for the driver. |
577 | // Type: Method. |
578 | // Args: None. |
579 | // Return: MIstatus::success - Functional succeeded. |
580 | // MIstatus::failure - Functional failed. |
581 | // Throws: None. |
582 | //-- |
583 | bool |
584 | CMIDriver::StopWorkerThreads(void) |
585 | { |
586 | CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); |
587 | return rThreadMgr.ThreadAllTerminate(); |
588 | } |
589 | |
590 | //++ ------------------------------------------------------------------------------------ |
591 | // Details: Call this function puts *this driver to work. |
592 | // This function is used by the application's main thread. |
593 | // Type: Overridden. |
594 | // Args: None. |
595 | // Return: MIstatus::success - Functional succeeded. |
596 | // MIstatus::failure - Functional failed. |
597 | // Throws: None. |
598 | //-- |
599 | bool |
600 | CMIDriver::DoMainLoop(void) |
601 | { |
602 | if (!InitClientIDEToMIDriver()) // Init Eclipse IDE |
603 | { |
604 | SetErrorDescriptionn(MIRSRC(IDS_MI_INIT_ERR_CLIENT_USING_DRIVER)CMICmnResources::Instance().GetString(IDS_MI_INIT_ERR_CLIENT_USING_DRIVER ).c_str()); |
605 | return MIstatus::failure; |
606 | } |
607 | |
608 | if (!StartWorkerThreads()) |
609 | return MIstatus::failure; |
610 | |
611 | // App is not quitting currently |
612 | m_bExitApp = false; |
613 | |
614 | // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION |
615 | #if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION0 |
616 | if (HaveExecutableFileNamePathOnCmdLine()) |
617 | { |
618 | if (!LocalDebugSessionStartupInjectCommands()) |
619 | { |
620 | SetErrorDescription(MIRSRC(IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION)CMICmnResources::Instance().GetString(IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION ).c_str()); |
621 | return MIstatus::failure; |
622 | } |
623 | } |
624 | #endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION |
625 | |
626 | // While the app is active |
627 | while (!m_bExitApp) |
628 | { |
629 | // Poll stdin queue and dispatch |
630 | if (!ReadStdinLineQueue()) |
631 | { |
632 | // Something went wrong |
633 | break; |
634 | } |
635 | } |
636 | |
637 | // Signal that the application is shutting down |
638 | DoAppQuit(); |
639 | |
640 | // Close and wait for the workers to stop |
641 | StopWorkerThreads(); |
642 | |
643 | // Ensure that a new line is sent as the last act of the dying driver |
644 | m_rStdOut.WriteMIResponse("\n", false); |
645 | |
646 | return MIstatus::success; |
647 | } |
648 | |
649 | //++ ------------------------------------------------------------------------------------ |
650 | // Details: *this driver sits and waits for input to the stdin line queue shared by *this |
651 | // driver and the stdin monitor thread, it queues, *this reads, interprets and |
652 | // reacts. |
653 | // This function is used by the application's main thread. |
654 | // Type: Method. |
655 | // Args: None. |
656 | // Return: MIstatus::success - Functional succeeded. |
657 | // MIstatus::failure - Functional failed. |
658 | // Throws: None. |
659 | //-- |
660 | bool |
661 | CMIDriver::ReadStdinLineQueue(void) |
662 | { |
663 | // True when queue contains input |
664 | bool bHaveInput = false; |
665 | |
666 | // Stores the current input line |
667 | CMIUtilString lineText; |
668 | { |
669 | // Lock while we access the queue |
670 | CMIUtilThreadLock lock(m_threadMutex); |
671 | if (!m_queueStdinLine.empty()) |
672 | { |
673 | lineText = m_queueStdinLine.front(); |
674 | m_queueStdinLine.pop(); |
675 | bHaveInput = !lineText.empty(); |
676 | } |
677 | } |
678 | |
679 | // Process while we have input |
680 | if (bHaveInput) |
681 | { |
682 | if (lineText == "quit") |
683 | { |
684 | // We want to be exiting when receiving a quit command |
685 | m_bExitApp = true; |
686 | return MIstatus::success; |
687 | } |
688 | |
689 | // Process the command |
690 | const bool bOk = InterpretCommand(lineText); |
691 | |
692 | // Draw prompt if desired |
693 | if (bOk && m_rStdin.GetEnablePrompt()) |
694 | m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt()); |
695 | |
696 | // Input has been processed |
697 | bHaveInput = false; |
Value stored to 'bHaveInput' is never read | |
698 | } |
699 | else |
700 | { |
701 | // Give resources back to the OS |
702 | const std::chrono::milliseconds time(1); |
703 | std::this_thread::sleep_for(time); |
704 | } |
705 | |
706 | return MIstatus::success; |
707 | } |
708 | |
709 | //++ ------------------------------------------------------------------------------------ |
710 | // Details: Set things in motion, set state etc that brings *this driver (and the |
711 | // application) to a tidy shutdown. |
712 | // This function is used by the application's main thread. |
713 | // Type: Method. |
714 | // Args: None. |
715 | // Return: MIstatus::success - Functional succeeded. |
716 | // MIstatus::failure - Functional failed. |
717 | // Throws: None. |
718 | //-- |
719 | bool |
720 | CMIDriver::DoAppQuit(void) |
721 | { |
722 | bool bYesQuit = true; |
723 | |
724 | // Shutdown stuff, ready app for exit |
725 | { |
726 | CMIUtilThreadLock lock(m_threadMutex); |
727 | m_bDriverIsExiting = true; |
728 | } |
729 | |
730 | return bYesQuit; |
731 | } |
732 | |
733 | //++ ------------------------------------------------------------------------------------ |
734 | // Details: *this driver passes text commands to a fall through driver is it does not |
735 | // understand them (the LLDB driver). |
736 | // This function is used by the application's main thread. |
737 | // Type: Method. |
738 | // Args: vTextLine - (R) Text data representing a possible command. |
739 | // vwbCmdYesValid - (W) True = Command valid, false = command not handled. |
740 | // Return: MIstatus::success - Functional succeeded. |
741 | // MIstatus::failure - Functional failed. |
742 | // Throws: None. |
743 | //-- |
744 | bool |
745 | CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) |
746 | { |
747 | MIunused(vTextLine)(void) vTextLine;; |
748 | MIunused(vwbCmdYesValid)(void) vwbCmdYesValid;; |
749 | |
750 | // ToDo: Implement when less urgent work to be done or decide remove as not required |
751 | // bool bOk = MIstatus::success; |
752 | // bool bCmdNotUnderstood = true; |
753 | // if( bCmdNotUnderstood && GetEnableFallThru() ) |
754 | //{ |
755 | // CMIUtilString errMsg; |
756 | // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg ); |
757 | // if( !bOk ) |
758 | // { |
759 | // errMsg = errMsg.StripCREndOfLine(); |
760 | // errMsg = errMsg.StripCRAll(); |
761 | // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); |
762 | // const MIchar * pName = pOtherDriver->GetDriverName().c_str(); |
763 | // const MIchar * pId = pOtherDriver->GetDriverId().c_str(); |
764 | // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) |
765 | //); |
766 | // m_pLog->WriteMsg( msg ); |
767 | // } |
768 | //} |
769 | // |
770 | // vwbCmdYesValid = bOk; |
771 | // CMIUtilString strNot; |
772 | // if( vwbCmdYesValid) |
773 | // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ); |
774 | // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) ); |
775 | // m_pLog->WriteLog( msg ); |
776 | |
777 | return MIstatus::success; |
778 | } |
779 | |
780 | //++ ------------------------------------------------------------------------------------ |
781 | // Details: Retrieve the name for *this driver. |
782 | // Type: Overridden. |
783 | // Args: None. |
784 | // Return: CMIUtilString & - Driver name. |
785 | // Throws: None. |
786 | //-- |
787 | const CMIUtilString & |
788 | CMIDriver::GetDriverName(void) const |
789 | { |
790 | return GetName(); |
791 | } |
792 | |
793 | //++ ------------------------------------------------------------------------------------ |
794 | // Details: Get the unique ID for *this driver. |
795 | // Type: Overridden. |
796 | // Args: None. |
797 | // Return: CMIUtilString & - Text description. |
798 | // Throws: None. |
799 | //-- |
800 | const CMIUtilString & |
801 | CMIDriver::GetDriverId(void) const |
802 | { |
803 | return GetId(); |
804 | } |
805 | |
806 | //++ ------------------------------------------------------------------------------------ |
807 | // Details: This function allows *this driver to call on another driver to perform work |
808 | // should this driver not be able to handle the client data input. |
809 | // SetDriverToFallThruTo() specifies the fall through to driver. |
810 | // Check the error message if the function returns a failure. |
811 | // Type: Overridden. |
812 | // Args: vCmd - (R) Command instruction to interpret. |
813 | // vwErrMsg - (W) Error description on command failing. |
814 | // Return: MIstatus::success - Command succeeded. |
815 | // MIstatus::failure - Command failed. |
816 | // Throws: None. |
817 | //-- |
818 | bool |
819 | CMIDriver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) |
820 | { |
821 | bool bOk = MIstatus::success; |
822 | |
823 | CMIDriverBase *pOtherDriver = GetDriverToFallThruTo(); |
824 | if (pOtherDriver == nullptr) |
825 | return bOk; |
826 | |
827 | return pOtherDriver->DoFallThruToAnotherDriver(vCmd, vwErrMsg); |
828 | } |
829 | |
830 | //++ ------------------------------------------------------------------------------------ |
831 | // Details: *this driver provides a file stream to other drivers on which *this driver |
832 | // write's out to and they read as expected input. *this driver is passing |
833 | // through commands to the (child) pass through assigned driver. |
834 | // Type: Overrdidden. |
835 | // Args: None. |
836 | // Return: FILE * - Pointer to stream. |
837 | // Throws: None. |
838 | //-- |
839 | FILE * |
840 | CMIDriver::GetStdin(void) const |
841 | { |
842 | // Note this fn is called on CMIDriverMgr register driver so stream has to be |
843 | // available before *this driver has been initialized! Flaw? |
844 | |
845 | // This very likely to change later to a stream that the pass thru driver |
846 | // will read and we write to give it 'input' |
847 | return stdinstdin; |
848 | } |
849 | |
850 | //++ ------------------------------------------------------------------------------------ |
851 | // Details: *this driver provides a file stream to other pass through assigned drivers |
852 | // so they know what to write to. |
853 | // Type: Overidden. |
854 | // Args: None. |
855 | // Return: FILE * - Pointer to stream. |
856 | // Throws: None. |
857 | //-- |
858 | FILE * |
859 | CMIDriver::GetStdout(void) const |
860 | { |
861 | // Note this fn is called on CMIDriverMgr register driver so stream has to be |
862 | // available before *this driver has been initialized! Flaw? |
863 | |
864 | // Do not want to pass through driver to write to stdout |
865 | return NULL__null; |
866 | } |
867 | |
868 | //++ ------------------------------------------------------------------------------------ |
869 | // Details: *this driver provides a error file stream to other pass through assigned drivers |
870 | // so they know what to write to. |
871 | // Type: Overidden. |
872 | // Args: None. |
873 | // Return: FILE * - Pointer to stream. |
874 | // Throws: None. |
875 | //-- |
876 | FILE * |
877 | CMIDriver::GetStderr(void) const |
878 | { |
879 | // Note this fn is called on CMIDriverMgr register driver so stream has to be |
880 | // available before *this driver has been initialized! Flaw? |
881 | |
882 | // This very likely to change later to a stream that the pass thru driver |
883 | // will write to and *this driver reads from to pass on the CMICmnLog object |
884 | return stderrstderr; |
885 | } |
886 | |
887 | //++ ------------------------------------------------------------------------------------ |
888 | // Details: Set a unique ID for *this driver. It cannot be empty. |
889 | // Type: Overridden. |
890 | // Args: vId - (R) Text description. |
891 | // Return: MIstatus::success - Functional succeeded. |
892 | // MIstatus::failure - Functional failed. |
893 | // Throws: None. |
894 | //-- |
895 | bool |
896 | CMIDriver::SetId(const CMIUtilString &vId) |
897 | { |
898 | if (vId.empty()) |
899 | { |
900 | SetErrorDescriptionn(MIRSRC(IDS_DRIVER_ERR_ID_INVALID)CMICmnResources::Instance().GetString(IDS_DRIVER_ERR_ID_INVALID ).c_str(), GetName().c_str(), vId.c_str()); |
901 | return MIstatus::failure; |
902 | } |
903 | |
904 | m_strDriverId = vId; |
905 | return MIstatus::success; |
906 | } |
907 | |
908 | //++ ------------------------------------------------------------------------------------ |
909 | // Details: Get the unique ID for *this driver. |
910 | // Type: Overridden. |
911 | // Args: None. |
912 | // Return: CMIUtilString & - Text description. |
913 | // Throws: None. |
914 | //-- |
915 | const CMIUtilString & |
916 | CMIDriver::GetId(void) const |
917 | { |
918 | return m_strDriverId; |
919 | } |
920 | |
921 | //++ ------------------------------------------------------------------------------------ |
922 | // Details: Inject a command into the command processing system to be interpreted as a |
923 | // command read from stdin. The text representing the command is also written |
924 | // out to stdout as the command did not come from via stdin. |
925 | // Type: Method. |
926 | // Args: vMICmd - (R) Text data representing a possible command. |
927 | // Return: MIstatus::success - Functional succeeded. |
928 | // MIstatus::failure - Functional failed. |
929 | // Throws: None. |
930 | //-- |
931 | bool |
932 | CMIDriver::InjectMICommand(const CMIUtilString &vMICmd) |
933 | { |
934 | const bool bOk = m_rStdOut.WriteMIResponse(vMICmd); |
935 | |
936 | return bOk && QueueMICommand(vMICmd); |
937 | } |
938 | |
939 | //++ ------------------------------------------------------------------------------------ |
940 | // Details: Add a new command candidate to the command queue to be processed by the |
941 | // command system. |
942 | // Type: Method. |
943 | // Args: vMICmd - (R) Text data representing a possible command. |
944 | // Return: MIstatus::success - Functional succeeded. |
945 | // MIstatus::failure - Functional failed. |
946 | // Throws: None. |
947 | //-- |
948 | bool |
949 | CMIDriver::QueueMICommand(const CMIUtilString &vMICmd) |
950 | { |
951 | CMIUtilThreadLock lock(m_threadMutex); |
952 | m_queueStdinLine.push(vMICmd); |
953 | |
954 | return MIstatus::success; |
955 | } |
956 | |
957 | //++ ------------------------------------------------------------------------------------ |
958 | // Details: Interpret the text data and match against current commands to see if there |
959 | // is a match. If a match then the command is issued and actioned on. The |
960 | // text data if not understood by *this driver is past on to the Fall Thru |
961 | // driver. |
962 | // This function is used by the application's main thread. |
963 | // Type: Method. |
964 | // Args: vTextLine - (R) Text data representing a possible command. |
965 | // Return: MIstatus::success - Functional succeeded. |
966 | // MIstatus::failure - Functional failed. |
967 | // Throws: None. |
968 | //-- |
969 | bool |
970 | CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) |
971 | { |
972 | bool bCmdYesValid = false; |
973 | bool bOk = InterpretCommandThisDriver(vTextLine, bCmdYesValid); |
974 | if (bOk && !bCmdYesValid) |
975 | bOk = InterpretCommandFallThruDriver(vTextLine, bCmdYesValid); |
976 | |
977 | return bOk; |
978 | } |
979 | |
980 | //++ ------------------------------------------------------------------------------------ |
981 | // Details: Interpret the text data and match against current commands to see if there |
982 | // is a match. If a match then the command is issued and actioned on. If a |
983 | // command cannot be found to match then vwbCmdYesValid is set to false and |
984 | // nothing else is done here. |
985 | // This function is used by the application's main thread. |
986 | // Type: Method. |
987 | // Args: vTextLine - (R) Text data representing a possible command. |
988 | // vwbCmdYesValid - (W) True = Command invalid, false = command acted on. |
989 | // Return: MIstatus::success - Functional succeeded. |
990 | // MIstatus::failure - Functional failed. |
991 | // Throws: None. |
992 | //-- |
993 | bool |
994 | CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) |
995 | { |
996 | vwbCmdYesValid = false; |
997 | |
998 | bool bCmdNotInCmdFactor = false; |
999 | SMICmdData cmdData; |
1000 | CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); |
1001 | if (!rCmdMgr.CmdInterpret(vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData)) |
1002 | return MIstatus::failure; |
1003 | |
1004 | if (vwbCmdYesValid) |
1005 | { |
1006 | // For debugging only |
1007 | // m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() ); |
1008 | |
1009 | return ExecuteCommand(cmdData); |
1010 | } |
1011 | |
1012 | // Check for escape character, may be cursor control characters |
1013 | // This code is not necessary for application operation, just want to keep tabs on what |
1014 | // is been given to the driver to try and intepret. |
1015 | if (vTextLine.at(0) == 27) |
1016 | { |
1017 | CMIUtilString logInput(MIRSRC(IDS_STDIN_INPUT_CTRL_CHARS)CMICmnResources::Instance().GetString(IDS_STDIN_INPUT_CTRL_CHARS ).c_str()); |
1018 | for (MIuint i = 0; i < vTextLine.length(); i++) |
1019 | { |
1020 | logInput += CMIUtilString::Format("%d ", vTextLine.at(i)); |
1021 | } |
1022 | m_pLog->WriteLog(logInput); |
1023 | return MIstatus::success; |
1024 | } |
1025 | |
1026 | // Write to the Log that a 'command' was not valid. |
1027 | // Report back to the MI client via MI result record. |
1028 | CMIUtilString strNotInCmdFactory; |
1029 | if (bCmdNotInCmdFactor) |
1030 | strNotInCmdFactory = CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_NOT_IN_FACTORY)CMICmnResources::Instance().GetString(IDS_DRIVER_CMD_NOT_IN_FACTORY ).c_str(), cmdData.strMiCmd.c_str()); |
1031 | const CMIUtilString strNot(CMIUtilString::Format("%s ", MIRSRC(IDS_WORD_NOT)CMICmnResources::Instance().GetString(IDS_WORD_NOT).c_str())); |
1032 | const CMIUtilString msg( |
1033 | CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_RECEIVED)CMICmnResources::Instance().GetString(IDS_DRIVER_CMD_RECEIVED ).c_str(), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str())); |
1034 | const CMICmnMIValueConst vconst = CMICmnMIValueConst(msg); |
1035 | const CMICmnMIValueResult valueResult("msg", vconst); |
1036 | const CMICmnMIResultRecord miResultRecord(cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult); |
1037 | m_rStdOut.WriteMIResponse(miResultRecord.GetString()); |
1038 | |
1039 | // Proceed to wait for or execute next command |
1040 | return MIstatus::success; |
1041 | } |
1042 | |
1043 | //++ ------------------------------------------------------------------------------------ |
1044 | // Details: Having previously had the potential command validated and found valid now |
1045 | // get the command executed. |
1046 | // This function is used by the application's main thread. |
1047 | // Type: Method. |
1048 | // Args: vCmdData - (RW) Command meta data. |
1049 | // Return: MIstatus::success - Functional succeeded. |
1050 | // MIstatus::failure - Functional failed. |
1051 | // Throws: None. |
1052 | //-- |
1053 | bool |
1054 | CMIDriver::ExecuteCommand(const SMICmdData &vCmdData) |
1055 | { |
1056 | CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); |
1057 | return rCmdMgr.CmdExecute(vCmdData); |
1058 | } |
1059 | |
1060 | //++ ------------------------------------------------------------------------------------ |
1061 | // Details: Set the MI Driver's exit application flag. The application checks this flag |
1062 | // after every stdin line is read so the exit may not be instantaneous. |
1063 | // If vbForceExit is false the MI Driver queries its state and determines if is |
1064 | // should exit or continue operating depending on that running state. |
1065 | // This is related to the running state of the MI driver. |
1066 | // Type: Overridden. |
1067 | // Args: None. |
1068 | // Return: None. |
1069 | // Throws: None. |
1070 | //-- |
1071 | void |
1072 | CMIDriver::SetExitApplicationFlag(const bool vbForceExit) |
1073 | { |
1074 | if (vbForceExit) |
1075 | { |
1076 | CMIUtilThreadLock lock(m_threadMutex); |
1077 | m_bExitApp = true; |
1078 | m_rStdin.OnExitHandler(); |
1079 | return; |
1080 | } |
1081 | |
1082 | // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM |
1083 | // Did we receive a SIGINT from the client during a running debug program, if |
1084 | // so then SIGINT is not to be taken as meaning kill the MI driver application |
1085 | // but halt the inferior program being debugged instead |
1086 | if (m_eCurrentDriverState == eDriverState_RunningDebugging) |
1087 | { |
1088 | InjectMICommand("-exec-interrupt"); |
1089 | return; |
1090 | } |
1091 | |
1092 | m_bExitApp = true; |
1093 | m_rStdin.OnExitHandler(); |
1094 | } |
1095 | |
1096 | //++ ------------------------------------------------------------------------------------ |
1097 | // Details: Get the MI Driver's exit exit application flag. |
1098 | // This is related to the running state of the MI driver. |
1099 | // Type: Method. |
1100 | // Args: None. |
1101 | // Return: bool - True = MI Driver is shutting down, false = MI driver is running. |
1102 | // Throws: None. |
1103 | //-- |
1104 | bool |
1105 | CMIDriver::GetExitApplicationFlag(void) const |
1106 | { |
1107 | return m_bExitApp; |
1108 | } |
1109 | |
1110 | //++ ------------------------------------------------------------------------------------ |
1111 | // Details: Get the current running state of the MI Driver. |
1112 | // Type: Method. |
1113 | // Args: None. |
1114 | // Return: DriverState_e - The current running state of the application. |
1115 | // Throws: None. |
1116 | //-- |
1117 | CMIDriver::DriverState_e |
1118 | CMIDriver::GetCurrentDriverState(void) const |
1119 | { |
1120 | return m_eCurrentDriverState; |
1121 | } |
1122 | |
1123 | //++ ------------------------------------------------------------------------------------ |
1124 | // Details: Set the current running state of the MI Driver to running and currently not in |
1125 | // a debug session. |
1126 | // Type: Method. |
1127 | // Return: MIstatus::success - Functionality succeeded. |
1128 | // MIstatus::failure - Functionality failed. |
1129 | // Return: DriverState_e - The current running state of the application. |
1130 | // Throws: None. |
1131 | //-- |
1132 | bool |
1133 | CMIDriver::SetDriverStateRunningNotDebugging(void) |
1134 | { |
1135 | // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM |
1136 | |
1137 | if (m_eCurrentDriverState == eDriverState_RunningNotDebugging) |
1138 | return MIstatus::success; |
1139 | |
1140 | // Driver cannot be in the following states to set eDriverState_RunningNotDebugging |
1141 | switch (m_eCurrentDriverState) |
1142 | { |
1143 | case eDriverState_NotRunning: |
1144 | case eDriverState_Initialising: |
1145 | case eDriverState_ShuttingDown: |
1146 | { |
1147 | SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)CMICmnResources::Instance().GetString(IDS_DRIVER_ERR_DRIVER_STATE_ERROR ).c_str()); |
1148 | return MIstatus::failure; |
1149 | } |
1150 | case eDriverState_RunningDebugging: |
1151 | case eDriverState_RunningNotDebugging: |
1152 | break; |
1153 | case eDriverState_count: |
1154 | SetErrorDescription( |
1155 | CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE)CMICmnResources::Instance().GetString(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ).c_str(), "SetDriverStateRunningNotDebugging()")); |
1156 | return MIstatus::failure; |
1157 | } |
1158 | |
1159 | // Driver must be in this state to set eDriverState_RunningNotDebugging |
1160 | if (m_eCurrentDriverState != eDriverState_RunningDebugging) |
1161 | { |
1162 | SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)CMICmnResources::Instance().GetString(IDS_DRIVER_ERR_DRIVER_STATE_ERROR ).c_str()); |
1163 | return MIstatus::failure; |
1164 | } |
1165 | |
1166 | m_eCurrentDriverState = eDriverState_RunningNotDebugging; |
1167 | |
1168 | return MIstatus::success; |
1169 | } |
1170 | |
1171 | //++ ------------------------------------------------------------------------------------ |
1172 | // Details: Set the current running state of the MI Driver to running and currently not in |
1173 | // a debug session. The driver's state must in the state running and in a |
1174 | // debug session to set this new state. |
1175 | // Type: Method. |
1176 | // Return: MIstatus::success - Functionality succeeded. |
1177 | // MIstatus::failure - Functionality failed. |
1178 | // Return: DriverState_e - The current running state of the application. |
1179 | // Throws: None. |
1180 | //-- |
1181 | bool |
1182 | CMIDriver::SetDriverStateRunningDebugging(void) |
1183 | { |
1184 | // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM |
1185 | |
1186 | if (m_eCurrentDriverState == eDriverState_RunningDebugging) |
1187 | return MIstatus::success; |
1188 | |
1189 | // Driver cannot be in the following states to set eDriverState_RunningDebugging |
1190 | switch (m_eCurrentDriverState) |
1191 | { |
1192 | case eDriverState_NotRunning: |
1193 | case eDriverState_Initialising: |
1194 | case eDriverState_ShuttingDown: |
1195 | { |
1196 | SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)CMICmnResources::Instance().GetString(IDS_DRIVER_ERR_DRIVER_STATE_ERROR ).c_str()); |
1197 | return MIstatus::failure; |
1198 | } |
1199 | case eDriverState_RunningDebugging: |
1200 | case eDriverState_RunningNotDebugging: |
1201 | break; |
1202 | case eDriverState_count: |
1203 | SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE)CMICmnResources::Instance().GetString(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ).c_str(), "SetDriverStateRunningDebugging()")); |
1204 | return MIstatus::failure; |
1205 | } |
1206 | |
1207 | // Driver must be in this state to set eDriverState_RunningDebugging |
1208 | if (m_eCurrentDriverState != eDriverState_RunningNotDebugging) |
1209 | { |
1210 | SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)CMICmnResources::Instance().GetString(IDS_DRIVER_ERR_DRIVER_STATE_ERROR ).c_str()); |
1211 | return MIstatus::failure; |
1212 | } |
1213 | |
1214 | m_eCurrentDriverState = eDriverState_RunningDebugging; |
1215 | |
1216 | return MIstatus::success; |
1217 | } |
1218 | |
1219 | //++ ------------------------------------------------------------------------------------ |
1220 | // Details: Prepare the client IDE so it will start working/communicating with *this MI |
1221 | // driver. |
1222 | // Type: Method. |
1223 | // Args: None. |
1224 | // Return: MIstatus::success - Functionality succeeded. |
1225 | // MIstatus::failure - Functionality failed. |
1226 | // Throws: None. |
1227 | //-- |
1228 | bool |
1229 | CMIDriver::InitClientIDEToMIDriver(void) const |
1230 | { |
1231 | // Put other IDE init functions here |
1232 | return InitClientIDEEclipse(); |
1233 | } |
1234 | |
1235 | //++ ------------------------------------------------------------------------------------ |
1236 | // Details: The IDE Eclipse when debugging locally expects "(gdb)\n" character |
1237 | // sequence otherwise it refuses to communicate and times out. This should be |
1238 | // sent to Eclipse before anything else. |
1239 | // Type: Method. |
1240 | // Args: None. |
1241 | // Return: MIstatus::success - Functionality succeeded. |
1242 | // MIstatus::failure - Functionality failed. |
1243 | // Throws: None. |
1244 | //-- |
1245 | bool |
1246 | CMIDriver::InitClientIDEEclipse(void) const |
1247 | { |
1248 | std::cout << "(gdb)" << std::endl; |
1249 | |
1250 | return MIstatus::success; |
1251 | } |
1252 | |
1253 | //++ ------------------------------------------------------------------------------------ |
1254 | // Details: Ask *this driver whether it found an executable in the MI Driver's list of |
1255 | // arguments which to open and debug. If so instigate commands to set up a debug |
1256 | // session for that executable. |
1257 | // Type: Method. |
1258 | // Args: None. |
1259 | // Return: bool - True = True = Yes executable given as one of the parameters to the MI |
1260 | // Driver. |
1261 | // False = not found. |
1262 | // Throws: None. |
1263 | //-- |
1264 | bool |
1265 | CMIDriver::HaveExecutableFileNamePathOnCmdLine(void) const |
1266 | { |
1267 | return m_bHaveExecutableFileNamePathOnCmdLine; |
1268 | } |
1269 | |
1270 | //++ ------------------------------------------------------------------------------------ |
1271 | // Details: Retrieve from *this driver executable file name path to start a debug session |
1272 | // with (if present see HaveExecutableFileNamePathOnCmdLine()). |
1273 | // Type: Method. |
1274 | // Args: None. |
1275 | // Return: CMIUtilString & - Executeable file name path or empty string. |
1276 | // Throws: None. |
1277 | //-- |
1278 | const CMIUtilString & |
1279 | CMIDriver::GetExecutableFileNamePathOnCmdLine(void) const |
1280 | { |
1281 | return m_strCmdLineArgExecuteableFileNamePath; |
1282 | } |
1283 | |
1284 | //++ ------------------------------------------------------------------------------------ |
1285 | // Details: Execute commands (by injecting them into the stdin line queue container) and |
1286 | // other code to set up the MI Driver such that is can take the executable |
1287 | // argument passed on the command and create a debug session for it. |
1288 | // Type: Method. |
1289 | // Args: None. |
1290 | // Return: MIstatus::success - Functionality succeeded. |
1291 | // MIstatus::failure - Functionality failed. |
1292 | // Throws: None. |
1293 | //-- |
1294 | bool |
1295 | CMIDriver::LocalDebugSessionStartupInjectCommands(void) |
1296 | { |
1297 | const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str())); |
1298 | |
1299 | return InjectMICommand(strCmd); |
1300 | } |
1301 | |
1302 | //++ ------------------------------------------------------------------------------------ |
1303 | // Details: Set the MI Driver into "its debugging an executable passed as an argument" |
1304 | // mode as against running via a client like Eclipse. |
1305 | // Type: Method. |
1306 | // Args: None. |
1307 | // Return: None. |
1308 | // Throws: None. |
1309 | //-- |
1310 | void |
1311 | CMIDriver::SetDriverDebuggingArgExecutable(void) |
1312 | { |
1313 | m_bDriverDebuggingArgExecutable = true; |
1314 | } |
1315 | |
1316 | //++ ------------------------------------------------------------------------------------ |
1317 | // Details: Retrieve the MI Driver state indicating if it is operating in "its debugging |
1318 | // an executable passed as an argument" mode as against running via a client |
1319 | // like Eclipse. |
1320 | // Type: Method. |
1321 | // Args: None. |
1322 | // Return: None. |
1323 | // Throws: None. |
1324 | //-- |
1325 | bool |
1326 | CMIDriver::IsDriverDebuggingArgExecutable(void) const |
1327 | { |
1328 | return m_bDriverDebuggingArgExecutable; |
1329 | } |