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