]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
Suppress excessive error prints in ENA TX hotpath
[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 //              --synchronous
386 //          The application's options --interpreter and --executable in code act
387 //          very similar.
388 //          The --executable is necessary to differentiate whether the MI Driver
389 //          is being
390 //          used by a client (e.g. Eclipse) or from the command line. Eclipse
391 //          issues the option
392 //          --interpreter and also passes additional arguments which can be
393 //          interpreted as an
394 //          executable if called from the command line. Using --executable tells
395 //          the MI Driver
396 //          it is being called from the command line and to prepare to launch
397 //          the executable
398 //          argument for a debug session. Using --interpreter on the command
399 //          line does not
400 //          issue additional commands to initialise a debug session.
401 //          Option --synchronous disables an asynchronous mode in the lldb-mi driver.
402 // Type:    Overridden.
403 // Args:    argc        - (R)   An integer that contains the count of arguments
404 // that follow in
405 //                              argv. The argc parameter is always greater than
406 //                              or equal to 1.
407 //          argv        - (R)   An array of null-terminated strings representing
408 //          command-line
409 //                              arguments entered by the user of the program. By
410 //                              convention,
411 //                              argv[0] is the command with which the program is
412 //                              invoked.
413 //          vpStdOut    - (R)   Pointer to a standard output stream.
414 //          vwbExiting  - (W)   True = *this want to exit, Reasons: help,
415 //          invalid arg(s),
416 //                              version information only.
417 //                              False = Continue to work, start debugger i.e.
418 //                              Command
419 //                              interpreter.
420 // Return:  lldb::SBError - LLDB current error status.
421 // Throws:  None.
422 //--
423 lldb::SBError CMIDriver::ParseArgs(const int argc, const char *argv[],
424                                    FILE *vpStdOut, bool &vwbExiting) {
425   lldb::SBError errStatus;
426   const bool bHaveArgs(argc >= 2);
427
428   // *** Add any args handled here to GetHelpOnCmdLineArgOptions() ***
429
430   // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
431   // Look for the command line options
432   bool bHaveExecutableFileNamePath = false;
433   bool bHaveExecutableLongOption = false;
434
435   if (bHaveArgs) {
436     // Search right to left to look for filenames
437     for (MIint i = argc - 1; i > 0; i--) {
438       const CMIUtilString strArg(argv[i]);
439       const CMICmdArgValFile argFile;
440
441       // Check for a filename
442       if (argFile.IsFilePath(strArg) ||
443           CMICmdArgValString(true, false, true).IsStringArg(strArg)) {
444         // Is this the command file for the '-s' or '--source' options?
445         const CMIUtilString strPrevArg(argv[i - 1]);
446         if (strPrevArg.compare("-s") == 0 ||
447             strPrevArg.compare("--source") == 0) {
448           m_strCmdLineArgCommandFileNamePath = strArg;
449           m_bHaveCommandFileNamePathOnCmdLine = true;
450           i--; // skip '-s' on the next loop
451           continue;
452         }
453         // Else, must be the executable
454         bHaveExecutableFileNamePath = true;
455         m_strCmdLineArgExecuteableFileNamePath = strArg;
456         m_bHaveExecutableFileNamePathOnCmdLine = true;
457       }
458       // Report error if no command file was specified for the '-s' or
459       // '--source' options
460       else if (strArg.compare("-s") == 0 || strArg.compare("--source") == 0) {
461         vwbExiting = true;
462         const CMIUtilString errMsg = CMIUtilString::Format(
463             MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strArg.c_str());
464         errStatus.SetErrorString(errMsg.c_str());
465         break;
466       }
467       // This argument is also checked for in CMIDriverMgr::ParseArgs()
468       else if (strArg.compare("--executable") == 0) // Used to specify that
469                                                     // there is executable
470                                                     // argument also on the
471                                                     // command line
472       {                                             // See fn description.
473         bHaveExecutableLongOption = true;
474       } else if (strArg.compare("--synchronous") == 0) {
475         CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().SetAsync(false);
476       }
477     }
478   }
479
480   if (bHaveExecutableFileNamePath && bHaveExecutableLongOption) {
481     SetDriverDebuggingArgExecutable();
482   }
483
484   return errStatus;
485 }
486
487 //++
488 //------------------------------------------------------------------------------------
489 // Details: A client can ask if *this driver is GDB/MI compatible.
490 // Type:    Overridden.
491 // Args:    None.
492 // Return:  True - GBD/MI compatible LLDB front end.
493 //          False - Not GBD/MI compatible LLDB front end.
494 // Throws:  None.
495 //--
496 bool CMIDriver::GetDriverIsGDBMICompatibleDriver() const { return true; }
497
498 //++
499 //------------------------------------------------------------------------------------
500 // Details: Start worker threads for the driver.
501 // Type:    Method.
502 // Args:    None.
503 // Return:  MIstatus::success - Functional succeeded.
504 //          MIstatus::failure - Functional failed.
505 // Throws:  None.
506 //--
507 bool CMIDriver::StartWorkerThreads() {
508   bool bOk = MIstatus::success;
509
510   // Grab the thread manager
511   CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance();
512
513   // Start the event polling thread
514   if (bOk && !rThreadMgr.ThreadStart<CMICmnLLDBDebugger>(m_rLldbDebugger)) {
515     const CMIUtilString errMsg = CMIUtilString::Format(
516         MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE),
517         CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str());
518     SetErrorDescription(errMsg);
519     return MIstatus::failure;
520   }
521
522   return bOk;
523 }
524
525 //++
526 //------------------------------------------------------------------------------------
527 // Details: Stop worker threads for the driver.
528 // Type:    Method.
529 // Args:    None.
530 // Return:  MIstatus::success - Functional succeeded.
531 //          MIstatus::failure - Functional failed.
532 // Throws:  None.
533 //--
534 bool CMIDriver::StopWorkerThreads() {
535   CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance();
536   return rThreadMgr.ThreadAllTerminate();
537 }
538
539 //++
540 //------------------------------------------------------------------------------------
541 // Details: Call this function puts *this driver to work.
542 //          This function is used by the application's main thread.
543 // Type:    Overridden.
544 // Args:    None.
545 // Return:  MIstatus::success - Functional succeeded.
546 //          MIstatus::failure - Functional failed.
547 // Throws:  None.
548 //--
549 bool CMIDriver::DoMainLoop() {
550   if (!InitClientIDEToMIDriver()) // Init Eclipse IDE
551   {
552     SetErrorDescriptionn(MIRSRC(IDS_MI_INIT_ERR_CLIENT_USING_DRIVER));
553     return MIstatus::failure;
554   }
555
556   if (!StartWorkerThreads())
557     return MIstatus::failure;
558
559   bool bOk = MIstatus::success;
560
561   if (HaveExecutableFileNamePathOnCmdLine()) {
562     if (!LocalDebugSessionStartupExecuteCommands()) {
563       SetErrorDescription(MIRSRC(IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION));
564       bOk = MIstatus::failure;
565     }
566   }
567
568   // App is not quitting currently
569   m_bExitApp = false;
570
571   // Handle source file
572   if (m_bHaveCommandFileNamePathOnCmdLine) {
573     const bool bAsyncMode = false;
574     ExecuteCommandFile(bAsyncMode);
575   }
576
577   // While the app is active
578   while (bOk && !m_bExitApp) {
579     CMIUtilString errorText;
580     const char *pCmd = m_rStdin.ReadLine(errorText);
581     if (pCmd != nullptr) {
582       CMIUtilString lineText(pCmd);
583       if (!lineText.empty()) {
584         // Check that the handler thread is alive (otherwise we stuck here)
585         assert(CMICmnLLDBDebugger::Instance().ThreadIsActive());
586
587         {
588           // Lock Mutex before processing commands so that we don't disturb an
589           // event
590           // being processed
591           CMIUtilThreadLock lock(
592               CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
593           bOk = InterpretCommand(lineText);
594         }
595
596         // Draw prompt if desired
597         bOk = bOk && CMICmnStreamStdout::WritePrompt();
598
599         // Wait while the handler thread handles incoming events
600         CMICmnLLDBDebugger::Instance().WaitForHandleEvent();
601       }
602     }
603   }
604
605   // Signal that the application is shutting down
606   DoAppQuit();
607
608   // Close and wait for the workers to stop
609   StopWorkerThreads();
610
611   return MIstatus::success;
612 }
613
614 //++
615 //------------------------------------------------------------------------------------
616 // Details: Set things in motion, set state etc that brings *this driver (and
617 // the
618 //          application) to a tidy shutdown.
619 //          This function is used by the application's main thread.
620 // Type:    Method.
621 // Args:    None.
622 // Return:  MIstatus::success - Functional succeeded.
623 //          MIstatus::failure - Functional failed.
624 // Throws:  None.
625 //--
626 bool CMIDriver::DoAppQuit() {
627   bool bYesQuit = true;
628
629   // Shutdown stuff, ready app for exit
630   {
631     CMIUtilThreadLock lock(m_threadMutex);
632     m_bDriverIsExiting = true;
633   }
634
635   return bYesQuit;
636 }
637
638 //++
639 //------------------------------------------------------------------------------------
640 // Details: *this driver passes text commands to a fall through driver is it
641 // does not
642 //          understand them (the LLDB driver).
643 //          This function is used by the application's main thread.
644 // Type:    Method.
645 // Args:    vTextLine           - (R) Text data representing a possible command.
646 //          vwbCmdYesValid      - (W) True = Command valid, false = command not
647 //          handled.
648 // Return:  MIstatus::success - Functional succeeded.
649 //          MIstatus::failure - Functional failed.
650 // Throws:  None.
651 //--
652 bool CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine,
653                                                bool &vwbCmdYesValid) {
654   MIunused(vTextLine);
655   MIunused(vwbCmdYesValid);
656
657   // ToDo: Implement when less urgent work to be done or decide remove as not
658   // required
659   // bool bOk = MIstatus::success;
660   // bool bCmdNotUnderstood = true;
661   // if( bCmdNotUnderstood && GetEnableFallThru() )
662   //{
663   //  CMIUtilString errMsg;
664   //  bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg );
665   //  if( !bOk )
666   //  {
667   //      errMsg = errMsg.StripCREndOfLine();
668   //      errMsg = errMsg.StripCRAll();
669   //      const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo();
670   //      const char * pName = pOtherDriver->GetDriverName().c_str();
671   //      const char * pId = pOtherDriver->GetDriverId().c_str();
672   //      const CMIUtilString msg( CMIUtilString::Format( MIRSRC(
673   //      IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() )
674   //);
675   //      m_pLog->WriteMsg( msg );
676   //  }
677   //}
678   //
679   // vwbCmdYesValid = bOk;
680   // CMIUtilString strNot;
681   // if( vwbCmdYesValid)
682   //  strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) );
683   // const CMIUtilString msg( CMIUtilString::Format( MIRSRC(
684   // IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) );
685   // m_pLog->WriteLog( msg );
686
687   return MIstatus::success;
688 }
689
690 //++
691 //------------------------------------------------------------------------------------
692 // Details: Retrieve the name for *this driver.
693 // Type:    Overridden.
694 // Args:    None.
695 // Return:  CMIUtilString & - Driver name.
696 // Throws:  None.
697 //--
698 const CMIUtilString &CMIDriver::GetDriverName() const { return GetName(); }
699
700 //++
701 //------------------------------------------------------------------------------------
702 // Details: Get the unique ID for *this driver.
703 // Type:    Overridden.
704 // Args:    None.
705 // Return:  CMIUtilString & - Text description.
706 // Throws:  None.
707 //--
708 const CMIUtilString &CMIDriver::GetDriverId() const { return GetId(); }
709
710 //++
711 //------------------------------------------------------------------------------------
712 // Details: This function allows *this driver to call on another driver to
713 // perform work
714 //          should this driver not be able to handle the client data input.
715 //          SetDriverToFallThruTo() specifies the fall through to driver.
716 //          Check the error message if the function returns a failure.
717 // Type:    Overridden.
718 // Args:    vCmd        - (R) Command instruction to interpret.
719 //          vwErrMsg    - (W) Status description on command failing.
720 // Return:  MIstatus::success - Command succeeded.
721 //          MIstatus::failure - Command failed.
722 // Throws:  None.
723 //--
724 bool CMIDriver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd,
725                                           CMIUtilString &vwErrMsg) {
726   bool bOk = MIstatus::success;
727
728   CMIDriverBase *pOtherDriver = GetDriverToFallThruTo();
729   if (pOtherDriver == nullptr)
730     return bOk;
731
732   return pOtherDriver->DoFallThruToAnotherDriver(vCmd, vwErrMsg);
733 }
734
735 //++
736 //------------------------------------------------------------------------------------
737 // Details: *this driver provides a file stream to other drivers on which *this
738 // driver
739 //          write's out to and they read as expected input. *this driver is
740 //          passing
741 //          through commands to the (child) pass through assigned driver.
742 // Type:    Overrdidden.
743 // Args:    None.
744 // Return:  FILE * - Pointer to stream.
745 // Throws:  None.
746 //--
747 FILE *CMIDriver::GetStdin() const {
748   // Note this fn is called on CMIDriverMgr register driver so stream has to be
749   // available before *this driver has been initialized! Flaw?
750
751   // This very likely to change later to a stream that the pass thru driver
752   // will read and we write to give it 'input'
753   return stdin;
754 }
755
756 //++
757 //------------------------------------------------------------------------------------
758 // Details: *this driver provides a file stream to other pass through assigned
759 // drivers
760 //          so they know what to write to.
761 // Type:    Overidden.
762 // Args:    None.
763 // Return:  FILE * - Pointer to stream.
764 // Throws:  None.
765 //--
766 FILE *CMIDriver::GetStdout() const {
767   // Note this fn is called on CMIDriverMgr register driver so stream has to be
768   // available before *this driver has been initialized! Flaw?
769
770   // Do not want to pass through driver to write to stdout
771   return NULL;
772 }
773
774 //++
775 //------------------------------------------------------------------------------------
776 // Details: *this driver provides a error file stream to other pass through
777 // assigned drivers
778 //          so they know what to write to.
779 // Type:    Overidden.
780 // Args:    None.
781 // Return:  FILE * - Pointer to stream.
782 // Throws:  None.
783 //--
784 FILE *CMIDriver::GetStderr() const {
785   // Note this fn is called on CMIDriverMgr register driver so stream has to be
786   // available before *this driver has been initialized! Flaw?
787
788   // This very likely to change later to a stream that the pass thru driver
789   // will write to and *this driver reads from to pass on the CMICmnLog object
790   return stderr;
791 }
792
793 //++
794 //------------------------------------------------------------------------------------
795 // Details: Set a unique ID for *this driver. It cannot be empty.
796 // Type:    Overridden.
797 // Args:    vId - (R) Text description.
798 // Return:  MIstatus::success - Functional succeeded.
799 //          MIstatus::failure - Functional failed.
800 // Throws:  None.
801 //--
802 bool CMIDriver::SetId(const CMIUtilString &vId) {
803   if (vId.empty()) {
804     SetErrorDescriptionn(MIRSRC(IDS_DRIVER_ERR_ID_INVALID), GetName().c_str(),
805                          vId.c_str());
806     return MIstatus::failure;
807   }
808
809   m_strDriverId = vId;
810   return MIstatus::success;
811 }
812
813 //++
814 //------------------------------------------------------------------------------------
815 // Details: Get the unique ID for *this driver.
816 // Type:    Overridden.
817 // Args:    None.
818 // Return:  CMIUtilString & - Text description.
819 // Throws:  None.
820 //--
821 const CMIUtilString &CMIDriver::GetId() const { return m_strDriverId; }
822
823 //++
824 //------------------------------------------------------------------------------------
825 // Details: Interpret the text data and match against current commands to see if
826 // there
827 //          is a match. If a match then the command is issued and actioned on.
828 //          The
829 //          text data if not understood by *this driver is past on to the Fall
830 //          Thru
831 //          driver.
832 //          This function is used by the application's main thread.
833 // Type:    Method.
834 // Args:    vTextLine   - (R) Text data representing a possible command.
835 // Return:  MIstatus::success - Functional succeeded.
836 //          MIstatus::failure - Functional failed.
837 // Throws:  None.
838 //--
839 bool CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) {
840   const bool bNeedToRebroadcastStopEvent =
841       m_rLldbDebugger.CheckIfNeedToRebroadcastStopEvent();
842   bool bCmdYesValid = false;
843   bool bOk = InterpretCommandThisDriver(vTextLine, bCmdYesValid);
844   if (bOk && !bCmdYesValid)
845     bOk = InterpretCommandFallThruDriver(vTextLine, bCmdYesValid);
846
847   if (bNeedToRebroadcastStopEvent)
848     m_rLldbDebugger.RebroadcastStopEvent();
849
850   return bOk;
851 }
852
853 //++
854 //------------------------------------------------------------------------------------
855 // Details: Helper function for CMIDriver::InterpretCommandThisDriver.
856 //          Convert a CLI command to MI command (just wrap any CLI command
857 //          into "<tokens>-interpreter-exec command \"<CLI command>\"").
858 // Type:    Method.
859 // Args:    vTextLine   - (R) Text data representing a possible command.
860 // Return:  CMIUtilString   - The original MI command or converted CLI command.
861 //          MIstatus::failure - Functional failed.
862 // Throws:  None.
863 //--
864 CMIUtilString
865 CMIDriver::WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const {
866   // Tokens contain following digits
867   static const CMIUtilString digits("0123456789");
868
869   // Consider an algorithm on the following example:
870   // 001-file-exec-and-symbols "/path/to/file"
871   //
872   // 1. Skip a command token
873   // For example:
874   // 001-file-exec-and-symbols "/path/to/file"
875   // 001target create "/path/to/file"
876   //    ^ -- command starts here (in both cases)
877   // Also possible case when command not found:
878   // 001
879   //    ^ -- i.e. only tokens are present (or empty string at all)
880   const size_t nCommandOffset = vTextLine.find_first_not_of(digits);
881
882   // 2. Check if command is empty
883   // For example:
884   // 001-file-exec-and-symbols "/path/to/file"
885   // 001target create "/path/to/file"
886   //    ^ -- command not empty (in both cases)
887   // or:
888   // 001
889   //    ^ -- command wasn't found
890   const bool bIsEmptyCommand = (nCommandOffset == CMIUtilString::npos);
891
892   // 3. Check and exit if it isn't a CLI command
893   // For example:
894   // 001-file-exec-and-symbols "/path/to/file"
895   // 001
896   //    ^ -- it isn't CLI command (in both cases)
897   // or:
898   // 001target create "/path/to/file"
899   //    ^ -- it's CLI command
900   const bool bIsCliCommand =
901       !bIsEmptyCommand && (vTextLine.at(nCommandOffset) != '-');
902   if (!bIsCliCommand)
903     return vTextLine;
904
905   // 4. Wrap CLI command to make it MI-compatible
906   //
907   // 001target create "/path/to/file"
908   // ^^^ -- token
909   const std::string vToken(vTextLine.begin(),
910                            vTextLine.begin() + nCommandOffset);
911   // 001target create "/path/to/file"
912   //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- CLI command
913   const CMIUtilString vCliCommand(std::string(vTextLine, nCommandOffset));
914
915   // 5. Escape special characters and embed the command in a string
916   // Result: it looks like -- target create \"/path/to/file\".
917   const std::string vShieldedCliCommand(vCliCommand.AddSlashes());
918
919   // 6. Turn the CLI command into an MI command, as in:
920   // 001-interpreter-exec command "target create \"/path/to/file\""
921   // ^^^ -- token
922   //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^                               ^ -- wrapper
923   //                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- shielded
924   //                               CLI command
925   return CMIUtilString::Format("%s-interpreter-exec command \"%s\"",
926                                vToken.c_str(), vShieldedCliCommand.c_str());
927 }
928
929 //++
930 //------------------------------------------------------------------------------------
931 // Details: Interpret the text data and match against current commands to see if
932 // there
933 //          is a match. If a match then the command is issued and actioned on.
934 //          If a
935 //          command cannot be found to match then vwbCmdYesValid is set to false
936 //          and
937 //          nothing else is done here.
938 //          This function is used by the application's main thread.
939 // Type:    Method.
940 // Args:    vTextLine           - (R) Text data representing a possible command.
941 //          vwbCmdYesValid      - (W) True = Command valid, false = command not
942 //          handled.
943 // Return:  MIstatus::success - Functional succeeded.
944 //          MIstatus::failure - Functional failed.
945 // Throws:  None.
946 //--
947 bool CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine,
948                                            bool &vwbCmdYesValid) {
949   // Convert any CLI commands into MI commands
950   const CMIUtilString vMITextLine(WrapCLICommandIntoMICommand(vTextLine));
951
952   vwbCmdYesValid = false;
953   bool bCmdNotInCmdFactor = false;
954   SMICmdData cmdData;
955   CMICmdMgr &rCmdMgr = CMICmdMgr::Instance();
956   if (!rCmdMgr.CmdInterpret(vMITextLine, vwbCmdYesValid, bCmdNotInCmdFactor,
957                             cmdData))
958     return MIstatus::failure;
959
960   if (vwbCmdYesValid) {
961     // For debugging only
962     // m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() );
963
964     return ExecuteCommand(cmdData);
965   }
966
967   // Check for escape character, may be cursor control characters
968   // This code is not necessary for application operation, just want to keep
969   // tabs on what
970   // has been given to the driver to try and interpret.
971   if (vMITextLine.at(0) == 27) {
972     CMIUtilString logInput(MIRSRC(IDS_STDIN_INPUT_CTRL_CHARS));
973     for (MIuint i = 0; i < vMITextLine.length(); i++) {
974       logInput += CMIUtilString::Format("%d ", vMITextLine.at(i));
975     }
976     m_pLog->WriteLog(logInput);
977     return MIstatus::success;
978   }
979
980   // Write to the Log that a 'command' was not valid.
981   // Report back to the MI client via MI result record.
982   CMIUtilString strNotInCmdFactory;
983   if (bCmdNotInCmdFactor)
984     strNotInCmdFactory = CMIUtilString::Format(
985         MIRSRC(IDS_DRIVER_CMD_NOT_IN_FACTORY), cmdData.strMiCmd.c_str());
986   const CMIUtilString strNot(
987       CMIUtilString::Format("%s ", MIRSRC(IDS_WORD_NOT)));
988   const CMIUtilString msg(CMIUtilString::Format(
989       MIRSRC(IDS_DRIVER_CMD_RECEIVED), vMITextLine.c_str(), strNot.c_str(),
990       strNotInCmdFactory.c_str()));
991   const CMICmnMIValueConst vconst = CMICmnMIValueConst(msg);
992   const CMICmnMIValueResult valueResult("msg", vconst);
993   const CMICmnMIResultRecord miResultRecord(
994       cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
995       valueResult);
996   const bool bOk = m_rStdOut.WriteMIResponse(miResultRecord.GetString());
997
998   // Proceed to wait for or execute next command
999   return bOk;
1000 }
1001
1002 //++
1003 //------------------------------------------------------------------------------------
1004 // Details: Having previously had the potential command validated and found
1005 // valid now
1006 //          get the command executed.
1007 //          This function is used by the application's main thread.
1008 // Type:    Method.
1009 // Args:    vCmdData    - (RW) Command meta data.
1010 // Return:  MIstatus::success - Functional succeeded.
1011 //          MIstatus::failure - Functional failed.
1012 // Throws:  None.
1013 //--
1014 bool CMIDriver::ExecuteCommand(const SMICmdData &vCmdData) {
1015   CMICmdMgr &rCmdMgr = CMICmdMgr::Instance();
1016   return rCmdMgr.CmdExecute(vCmdData);
1017 }
1018
1019 //++
1020 //------------------------------------------------------------------------------------
1021 // Details: Set the MI Driver's exit application flag. The application checks
1022 // this flag
1023 //          after every stdin line is read so the exit may not be instantaneous.
1024 //          If vbForceExit is false the MI Driver queries its state and
1025 //          determines if is
1026 //          should exit or continue operating depending on that running state.
1027 //          This is related to the running state of the MI driver.
1028 // Type:    Overridden.
1029 // Args:    None.
1030 // Return:  None.
1031 // Throws:  None.
1032 //--
1033 void CMIDriver::SetExitApplicationFlag(const bool vbForceExit) {
1034   if (vbForceExit) {
1035     CMIUtilThreadLock lock(m_threadMutex);
1036     m_bExitApp = true;
1037     return;
1038   }
1039
1040   // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
1041   // Did we receive a SIGINT from the client during a running debug program, if
1042   // so then SIGINT is not to be taken as meaning kill the MI driver application
1043   // but halt the inferior program being debugged instead
1044   if (m_eCurrentDriverState == eDriverState_RunningDebugging) {
1045     InterpretCommand("-exec-interrupt");
1046     return;
1047   }
1048
1049   m_bExitApp = true;
1050 }
1051
1052 //++
1053 //------------------------------------------------------------------------------------
1054 // Details: Get the  MI Driver's exit exit application flag.
1055 //          This is related to the running state of the MI driver.
1056 // Type:    Method.
1057 // Args:    None.
1058 // Return:  bool    - True = MI Driver is shutting down, false = MI driver is
1059 // running.
1060 // Throws:  None.
1061 //--
1062 bool CMIDriver::GetExitApplicationFlag() const { return m_bExitApp; }
1063
1064 //++
1065 //------------------------------------------------------------------------------------
1066 // Details: Get the current running state of the MI Driver.
1067 // Type:    Method.
1068 // Args:    None.
1069 // Return:  DriverState_e   - The current running state of the application.
1070 // Throws:  None.
1071 //--
1072 CMIDriver::DriverState_e CMIDriver::GetCurrentDriverState() const {
1073   return m_eCurrentDriverState;
1074 }
1075
1076 //++
1077 //------------------------------------------------------------------------------------
1078 // Details: Set the current running state of the MI Driver to running and
1079 // currently not in
1080 //          a debug session.
1081 // Type:    Method.
1082 // Return:  MIstatus::success - Functionality succeeded.
1083 //          MIstatus::failure - Functionality failed.
1084 // Return:  DriverState_e   - The current running state of the application.
1085 // Throws:  None.
1086 //--
1087 bool CMIDriver::SetDriverStateRunningNotDebugging() {
1088   // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
1089
1090   if (m_eCurrentDriverState == eDriverState_RunningNotDebugging)
1091     return MIstatus::success;
1092
1093   // Driver cannot be in the following states to set
1094   // eDriverState_RunningNotDebugging
1095   switch (m_eCurrentDriverState) {
1096   case eDriverState_NotRunning:
1097   case eDriverState_Initialising:
1098   case eDriverState_ShuttingDown: {
1099     SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR));
1100     return MIstatus::failure;
1101   }
1102   case eDriverState_RunningDebugging:
1103   case eDriverState_RunningNotDebugging:
1104     break;
1105   case eDriverState_count:
1106     SetErrorDescription(
1107         CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE),
1108                               "SetDriverStateRunningNotDebugging()"));
1109     return MIstatus::failure;
1110   }
1111
1112   // Driver must be in this state to set eDriverState_RunningNotDebugging
1113   if (m_eCurrentDriverState != eDriverState_RunningDebugging) {
1114     SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR));
1115     return MIstatus::failure;
1116   }
1117
1118   m_eCurrentDriverState = eDriverState_RunningNotDebugging;
1119
1120   return MIstatus::success;
1121 }
1122
1123 //++
1124 //------------------------------------------------------------------------------------
1125 // Details: Set the current running state of the MI Driver to running and
1126 // currently not in
1127 //          a debug session. The driver's state must in the state running and in
1128 //          a
1129 //          debug session to set this new state.
1130 // Type:    Method.
1131 // Return:  MIstatus::success - Functionality succeeded.
1132 //          MIstatus::failure - Functionality failed.
1133 // Return:  DriverState_e   - The current running state of the application.
1134 // Throws:  None.
1135 //--
1136 bool CMIDriver::SetDriverStateRunningDebugging() {
1137   // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
1138
1139   if (m_eCurrentDriverState == eDriverState_RunningDebugging)
1140     return MIstatus::success;
1141
1142   // Driver cannot be in the following states to set
1143   // eDriverState_RunningDebugging
1144   switch (m_eCurrentDriverState) {
1145   case eDriverState_NotRunning:
1146   case eDriverState_Initialising:
1147   case eDriverState_ShuttingDown: {
1148     SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR));
1149     return MIstatus::failure;
1150   }
1151   case eDriverState_RunningDebugging:
1152   case eDriverState_RunningNotDebugging:
1153     break;
1154   case eDriverState_count:
1155     SetErrorDescription(
1156         CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE),
1157                               "SetDriverStateRunningDebugging()"));
1158     return MIstatus::failure;
1159   }
1160
1161   // Driver must be in this state to set eDriverState_RunningDebugging
1162   if (m_eCurrentDriverState != eDriverState_RunningNotDebugging) {
1163     SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR));
1164     return MIstatus::failure;
1165   }
1166
1167   m_eCurrentDriverState = eDriverState_RunningDebugging;
1168
1169   return MIstatus::success;
1170 }
1171
1172 //++
1173 //------------------------------------------------------------------------------------
1174 // Details: Prepare the client IDE so it will start working/communicating with
1175 // *this MI
1176 //          driver.
1177 // Type:    Method.
1178 // Args:    None.
1179 // Return:  MIstatus::success - Functionality succeeded.
1180 //          MIstatus::failure - Functionality failed.
1181 // Throws:  None.
1182 //--
1183 bool CMIDriver::InitClientIDEToMIDriver() const {
1184   // Put other IDE init functions here
1185   return InitClientIDEEclipse();
1186 }
1187
1188 //++
1189 //------------------------------------------------------------------------------------
1190 // Details: The IDE Eclipse when debugging locally expects "(gdb)\n" character
1191 //          sequence otherwise it refuses to communicate and times out. This
1192 //          should be
1193 //          sent to Eclipse before anything else.
1194 // Type:    Method.
1195 // Args:    None.
1196 // Return:  MIstatus::success - Functionality succeeded.
1197 //          MIstatus::failure - Functionality failed.
1198 // Throws:  None.
1199 //--
1200 bool CMIDriver::InitClientIDEEclipse() const {
1201   return CMICmnStreamStdout::WritePrompt();
1202 }
1203
1204 //++
1205 //------------------------------------------------------------------------------------
1206 // Details: Ask *this driver whether it found an executable in the MI Driver's
1207 // list of
1208 //          arguments which to open and debug. If so instigate commands to set
1209 //          up a debug
1210 //          session for that executable.
1211 // Type:    Method.
1212 // Args:    None.
1213 // Return:  bool - True = True = Yes executable given as one of the parameters
1214 // to the MI
1215 //                 Driver.
1216 //                 False = not found.
1217 // Throws:  None.
1218 //--
1219 bool CMIDriver::HaveExecutableFileNamePathOnCmdLine() const {
1220   return m_bHaveExecutableFileNamePathOnCmdLine;
1221 }
1222
1223 //++
1224 //------------------------------------------------------------------------------------
1225 // Details: Retrieve from *this driver executable file name path to start a
1226 // debug session
1227 //          with (if present see HaveExecutableFileNamePathOnCmdLine()).
1228 // Type:    Method.
1229 // Args:    None.
1230 // Return:  CMIUtilString & - Executeable file name path or empty string.
1231 // Throws:  None.
1232 //--
1233 const CMIUtilString &CMIDriver::GetExecutableFileNamePathOnCmdLine() const {
1234   return m_strCmdLineArgExecuteableFileNamePath;
1235 }
1236
1237 //++
1238 //------------------------------------------------------------------------------------
1239 // Details: Execute commands (by injecting them into the stdin line queue
1240 // container) and
1241 //          other code to set up the MI Driver such that is can take the
1242 //          executable
1243 //          argument passed on the command and create a debug session for it.
1244 // Type:    Method.
1245 // Args:    None.
1246 // Return:  MIstatus::success - Functionality succeeded.
1247 //          MIstatus::failure - Functionality failed.
1248 // Throws:  None.
1249 //--
1250 bool CMIDriver::LocalDebugSessionStartupExecuteCommands() {
1251   const CMIUtilString strCmd(CMIUtilString::Format(
1252       "-file-exec-and-symbols \"%s\"",
1253       m_strCmdLineArgExecuteableFileNamePath.AddSlashes().c_str()));
1254   bool bOk = CMICmnStreamStdout::TextToStdout(strCmd);
1255   bOk = bOk && InterpretCommand(strCmd);
1256   bOk = bOk && CMICmnStreamStdout::WritePrompt();
1257   return bOk;
1258 }
1259
1260 //++
1261 //------------------------------------------------------------------------------------
1262 // Details: Set the MI Driver into "its debugging an executable passed as an
1263 // argument"
1264 //          mode as against running via a client like Eclipse.
1265 // Type:    Method.
1266 // Args:    None.
1267 // Return:  None.
1268 // Throws:  None.
1269 //--
1270 void CMIDriver::SetDriverDebuggingArgExecutable() {
1271   m_bDriverDebuggingArgExecutable = true;
1272 }
1273
1274 //++
1275 //------------------------------------------------------------------------------------
1276 // Details: Retrieve the MI Driver state indicating if it is operating in "its
1277 // debugging
1278 //          an executable passed as an argument" mode as against running via a
1279 //          client
1280 //          like Eclipse.
1281 // Type:    Method.
1282 // Args:    None.
1283 // Return:  None.
1284 // Throws:  None.
1285 //--
1286 bool CMIDriver::IsDriverDebuggingArgExecutable() const {
1287   return m_bDriverDebuggingArgExecutable;
1288 }
1289
1290 //++
1291 //------------------------------------------------------------------------------------
1292 // Details: Execute commands from command source file in specified mode, and
1293 //          set exit-flag if needed.
1294 // Type:    Method.
1295 // Args:    vbAsyncMode       - (R) True = execute commands in asynchronous
1296 // mode, false = otherwise.
1297 // Return:  MIstatus::success - Function succeeded.
1298 //          MIstatus::failure - Function failed.
1299 // Throws:  None.
1300 //--
1301 bool CMIDriver::ExecuteCommandFile(const bool vbAsyncMode) {
1302   std::ifstream ifsStartScript(m_strCmdLineArgCommandFileNamePath.c_str());
1303   if (!ifsStartScript.is_open()) {
1304     const CMIUtilString errMsg(
1305         CMIUtilString::Format(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN),
1306                               m_strCmdLineArgCommandFileNamePath.c_str()));
1307     SetErrorDescription(errMsg.c_str());
1308     const bool bForceExit = true;
1309     SetExitApplicationFlag(bForceExit);
1310     return MIstatus::failure;
1311   }
1312
1313   // Switch lldb to synchronous mode
1314   CMICmnLLDBDebugSessionInfo &rSessionInfo(
1315       CMICmnLLDBDebugSessionInfo::Instance());
1316   const bool bAsyncSetting = rSessionInfo.GetDebugger().GetAsync();
1317   rSessionInfo.GetDebugger().SetAsync(vbAsyncMode);
1318
1319   // Execute commands from file
1320   bool bOk = MIstatus::success;
1321   CMIUtilString strCommand;
1322   while (!m_bExitApp && std::getline(ifsStartScript, strCommand)) {
1323     // Print command
1324     bOk = CMICmnStreamStdout::TextToStdout(strCommand);
1325
1326     // Skip if it's a comment or empty line
1327     if (strCommand.empty() || strCommand[0] == '#')
1328       continue;
1329
1330     // Execute if no error
1331     if (bOk) {
1332       CMIUtilThreadLock lock(rSessionInfo.GetSessionMutex());
1333       bOk = InterpretCommand(strCommand);
1334     }
1335
1336     // Draw the prompt after command will be executed (if enabled)
1337     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1338
1339     // Exit if there is an error
1340     if (!bOk) {
1341       const bool bForceExit = true;
1342       SetExitApplicationFlag(bForceExit);
1343       break;
1344     }
1345
1346     // Wait while the handler thread handles incoming events
1347     CMICmnLLDBDebugger::Instance().WaitForHandleEvent();
1348   }
1349
1350   // Switch lldb back to initial mode
1351   rSessionInfo.GetDebugger().SetAsync(bAsyncSetting);
1352
1353   return bOk;
1354 }
1355
1356 //++
1357 //------------------------------------------------------------------------------------
1358 // Details: Gets called when lldb-mi gets a signal. Stops the process if it was
1359 // SIGINT.
1360 //
1361 // Type:    Method.
1362 // Args:    signal that was delivered
1363 // Return:  None.
1364 // Throws:  None.
1365 //--
1366 void CMIDriver::DeliverSignal(int signal) {
1367   if (signal == SIGINT &&
1368       (m_eCurrentDriverState == eDriverState_RunningDebugging))
1369     InterpretCommand("-exec-interrupt");
1370 }