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