aboutsummaryrefslogtreecommitdiff
path: root/tools/lldb-mi/MIDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lldb-mi/MIDriver.cpp')
-rw-r--r--tools/lldb-mi/MIDriver.cpp1276
1 files changed, 1276 insertions, 0 deletions
diff --git a/tools/lldb-mi/MIDriver.cpp b/tools/lldb-mi/MIDriver.cpp
new file mode 100644
index 000000000000..759d54a5364d
--- /dev/null
+++ b/tools/lldb-mi/MIDriver.cpp
@@ -0,0 +1,1276 @@
+//===-- MIDriver.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriver.cpp
+//
+// Overview: CMIDriver implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <stdarg.h> // va_list, va_start, var_end
+#include <iostream>
+#include <lldb/API/SBError.h>
+
+// In-house headers:
+#include "Driver.h"
+#include "MIDriver.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmdMgr.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnThreadMgrStd.h"
+#include "MIUtilDebug.h"
+#include "MIUtilSingletonHelper.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnStreamStderr.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValString.h"
+#include "MICmnConfig.h"
+
+// Instantiations:
+#if _DEBUG
+ const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC( IDS_MI_VERSION_DESCRIPTION_DEBUG );
+#else
+ const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC( IDS_MI_VERSION_DESCRIPTION ); // Matches version in resources file
+#endif // _DEBUG
+const CMIUtilString CMIDriver::ms_constAppNameShort( MIRSRC( IDS_MI_APPNAME_SHORT ) );
+const CMIUtilString CMIDriver::ms_constAppNameLong( MIRSRC( IDS_MI_APPNAME_LONG ) );
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriver constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriver::CMIDriver( void )
+: m_bFallThruToOtherDriverEnabled( false )
+, m_bDriverIsExiting( false )
+, m_handleMainThread( 0 )
+, m_rStdin( CMICmnStreamStdin::Instance() )
+, m_rLldbDebugger( CMICmnLLDBDebugger::Instance() )
+, m_rStdOut( CMICmnStreamStdout::Instance() )
+, m_eCurrentDriverState( eDriverState_NotRunning )
+, m_bHaveExecutableFileNamePathOnCmdLine( false )
+, m_bDriverDebuggingArgExecutable( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriver destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriver::~CMIDriver( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set whether *this driver (the parent) is enabled to pass a command to its
+// fall through (child) driver to interpret the command and do work instead
+// (if *this driver decides it can't hanled the command).
+// Type: Method.
+// Args: vbYes - (R) True = yes fall through, false = do not pass on command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::SetEnableFallThru( const bool vbYes )
+{
+ m_bFallThruToOtherDriverEnabled = vbYes;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get whether *this driver (the parent) is enabled to pass a command to its
+// fall through (child) driver to interpret the command and do work instead
+// (if *this driver decides it can't hanled the command).
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes fall through, false = do not pass on command.
+// Throws: None.
+//--
+bool CMIDriver::GetEnableFallThru( void ) const
+{
+ return m_bFallThruToOtherDriverEnabled;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's application name of itself.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetAppNameShort( void ) const
+{
+ return ms_constAppNameShort;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's application name of itself.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetAppNameLong( void ) const
+{
+ return ms_constAppNameLong;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's version description of itself.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetVersionDescription( void ) const
+{
+ return ms_constMIVersion;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize setup *this driver ready for use.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::Initialize( void )
+{
+ m_eCurrentDriverState = eDriverState_Initialising;
+ m_clientUsageRefCnt++;
+
+ ClrErrorDescription();
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Initialize all of the modules we depend on
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg );
+ MI::ModuleInit< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg );
+ MI::ModuleInit< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg );
+ MI::ModuleInit< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg );
+ MI::ModuleInit< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg );
+ bOk &= m_rLldbDebugger.SetDriver( *this );
+ MI::ModuleInit< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg );
+
+#if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+ CMIDriverMgr & rDrvMgr = CMIDriverMgr::Instance();
+ bOk = bOk && rDrvMgr.RegisterDriver( *g_driver, "LLDB driver" ); // Will be pass thru driver
+ if( bOk )
+ {
+ bOk = SetEnableFallThru( false ); // This is intentional at this time - yet to be fully implemented
+ bOk = bOk && SetDriverToFallThruTo( *g_driver );
+ CMIUtilString strOtherDrvErrMsg;
+ if( bOk && GetEnableFallThru() && !g_driver->MISetup( strOtherDrvErrMsg ) )
+ {
+ bOk = false;
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_FALLTHRUDRIVER ), strOtherDrvErrMsg.c_str() );
+ }
+ }
+#endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
+ m_bExitApp = false;
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ const CMIUtilString msg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVER ), errMsg.c_str() );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+
+ m_eCurrentDriverState = eDriverState_RunningNotDebugging;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unbind detach or release resources used by *this driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_eCurrentDriverState = eDriverState_ShuttingDown;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Shutdown all of the modules we depend on
+ MI::ModuleShutdown< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg );
+ MI::ModuleShutdown< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() );
+ }
+
+ m_eCurrentDriverState = eDriverState_NotRunning;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Work function. Client (the driver's user) is able to append their own message
+// in to the MI's Log trace file.
+// Type: Method.
+// Args: vMessage - (R) Client's text message.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::WriteMessageToLog( const CMIUtilString & vMessage )
+{
+ CMIUtilString msg;
+ msg = CMIUtilString::Format( MIRSRC( IDS_MI_CLIENT_MSG ), vMessage.c_str() );
+ return m_pLog->Write( msg, CMICmnLog::eLogVerbosity_ClientMsg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDriverMgr calls *this driver initialize setup ready for use.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoInitialize( void )
+{
+ return CMIDriver::Instance().Initialize();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDriverMgr calls *this driver to unbind detach or release resources used by
+// *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoShutdown( void )
+{
+ return CMIDriver::Instance().Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Driver name.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetName( void ) const
+{
+ const CMIUtilString & rName = GetAppNameLong();
+ const CMIUtilString & rVsn = GetVersionDescription();
+ static CMIUtilString strName = CMIUtilString::Format( "%s %s", rName.c_str(), rVsn.c_str() );
+
+ return strName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve *this driver's last error condition.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString CMIDriver::GetError( void ) const
+{
+ return GetErrorDescription();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to resize the console window.
+// Type: Overridden.
+// Args: vTermWidth - (R) New window column size.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void CMIDriver::DoResizeWindow( const uint32_t vTermWidth )
+{
+ GetTheDebugger().SetTerminalWidth( vTermWidth );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to return it's debugger.
+// Type: Overridden.
+// Args: None.
+// Return: lldb::SBDebugger & - LLDB debugger object reference.
+// Throws: None.
+//--
+lldb::SBDebugger & CMIDriver::GetTheDebugger( void )
+{
+ return m_rLldbDebugger.GetTheDebugger();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Specify another driver *this driver can call should this driver not be able
+// to handle the client data input. DoFallThruToAnotherDriver() makes the call.
+// Type: Overridden.
+// Args: vrOtherDriver - (R) Reference to another driver object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver )
+{
+ m_pDriverFallThru = const_cast< CMIDriverBase * >( &vrOtherDriver );
+
+ return m_pDriverFallThru->SetDriverParent( *this );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Proxy function CMIDriverMgr IDriver interface implementation. *this driver's
+// implementation called from here to match the existing function name of the
+// original LLDb driver class (the extra indirection is not necessarily required).
+// Check the arguments that were passed to this program to make sure they are
+// valid and to get their argument values (if any).
+// Type: Overridden.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vpStdOut - (R) Pointer to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
+// version information only.
+// False = Continue to work, start debugger i.e. Command
+// interpreter.
+// Return: lldb::SBError - LLDB current error status.
+// Throws: None.
+//--
+lldb::SBError CMIDriver::DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ return ParseArgs( argc, argv, vpStdOut, vwbExiting );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check the arguments that were passed to this program to make sure they are
+// valid and to get their argument values (if any). The following are options
+// that are only handled by *this driver:
+// --executable
+// The application's options --interpreter and --executable in code act very similar.
+// The --executable is necessary to differentiate whither the MI Driver is being
+// using by a client i.e. Eclipse or from the command line. Eclipse issues the option
+// --interpreter and also passes additional arguments which can be interpreted as an
+// executable if called from the command line. Using --executable tells the MI
+// Driver is being called the command line and that the executable argument is indeed
+// a specified executable an so actions commands to set up the executable for a
+// debug session. Using --interpreter on the commnd line does not action additional
+// commands to initialise a debug session and so be able to launch the process.
+// Type: Overridden.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vpStdOut - (R) Pointer to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
+// version information only.
+// False = Continue to work, start debugger i.e. Command
+// interpreter.
+// Return: lldb::SBError - LLDB current error status.
+// Throws: None.
+//--
+lldb::SBError CMIDriver::ParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ lldb::SBError errStatus;
+ const bool bHaveArgs( argc >= 2 );
+
+ // *** Add any args handled here to GetHelpOnCmdLineArgOptions() ***
+
+ // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
+ // Look for the command line options
+ bool bHaveExecutableFileNamePath = false;
+ bool bHaveExecutableLongOption = false;
+
+ if( bHaveArgs )
+ {
+ // Search right to left to look for the executable
+ for( MIint i = argc - 1; i > 0; i-- )
+ {
+ const CMIUtilString strArg( argv[ i ] );
+ const CMICmdArgValFile argFile;
+ if( argFile.IsFilePath( strArg ) ||
+ CMICmdArgValString( true, false, true ).IsStringArg( strArg ))
+ {
+ bHaveExecutableFileNamePath = true;
+ m_strCmdLineArgExecuteableFileNamePath = argFile.GetFileNamePath( strArg );
+ m_bHaveExecutableFileNamePathOnCmdLine = true;
+ }
+ // This argument is also check for in CMIDriverMgr::ParseArgs()
+ if( 0 == strArg.compare( "--executable" ) ) // Used to specify that there is executable argument also on the command line
+ { // See fn description.
+ bHaveExecutableLongOption = true;
+ }
+ }
+ }
+
+ if( bHaveExecutableFileNamePath && bHaveExecutableLongOption )
+ {
+ // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+#if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+ SetDriverDebuggingArgExecutable();
+#else
+ vwbExiting = true;
+ errStatus.SetErrorString( MIRSRC( IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL ) );
+#endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+ }
+
+ return errStatus;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A client can ask if *this driver is GDB/MI compatible.
+// Type: Overridden.
+// Args: None.
+// Return: True - GBD/MI compatible LLDB front end.
+// False - Not GBD/MI compatible LLDB front end.
+// Throws: None.
+//--
+bool CMIDriver::GetDriverIsGDBMICompatibleDriver( void ) const
+{
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Callback function for monitoring stream stdin object. Part of the visitor
+// pattern.
+// This function is called by the CMICmnStreamStdin::CThreadStdin
+// "stdin monitor" thread (ID).
+// Type: Overridden.
+// Args: vStdInBuffer - (R) Copy of the current stdin line data.
+// vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::ReadLine( const CMIUtilString & vStdInBuffer, bool & vrwbYesExit )
+{
+ // For debugging. Update prompt show stdin is working
+ //printf( "%s\n", vStdInBuffer.c_str() );
+ //fflush( stdout );
+
+ // Special case look for the quit command here so stop monitoring stdin stream
+ // So we do not go back to fgetc() and wait and hang thread on exit
+ if( vStdInBuffer == "quit" )
+ vrwbYesExit = true;
+
+ // 1. Put new line in the queue container by stdin monitor thread
+ // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its
+ // own thread
+ const bool bOk = QueueMICommand( vStdInBuffer );
+
+ // Check to see if the *this driver is shutting down (exit application)
+ if( !vrwbYesExit )
+ vrwbYesExit = m_bDriverIsExiting;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Start worker threads for the driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::StartWorkerThreads( void )
+{
+ bool bOk = MIstatus::success;
+
+ // Grab the thread manager
+ CMICmnThreadMgrStd & rThreadMgr = CMICmnThreadMgrStd::Instance();
+
+ // Start the stdin thread
+ bOk &= m_rStdin.SetVisitor( *this );
+ if( bOk && !rThreadMgr.ThreadStart< CMICmnStreamStdin >( m_rStdin ))
+ {
+ const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str() );
+ SetErrorDescriptionn( errMsg );
+ return MIstatus::failure;
+ }
+
+ // Start the event polling thread
+ if( bOk && !rThreadMgr.ThreadStart< CMICmnLLDBDebugger >( m_rLldbDebugger ) )
+ {
+ const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str() );
+ SetErrorDescriptionn( errMsg );
+ return MIstatus::failure;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Stop worker threads for the driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::StopWorkerThreads( void )
+{
+ CMICmnThreadMgrStd & rThreadMgr = CMICmnThreadMgrStd::Instance();
+ return rThreadMgr.ThreadAllTerminate();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call this function puts *this driver to work.
+// This function is used by the application's main thread.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoMainLoop( void )
+{
+ if( !InitClientIDEToMIDriver() ) // Init Eclipse IDE
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_INIT_ERR_CLIENT_USING_DRIVER ) );
+ return MIstatus::failure;
+ }
+
+ if( !StartWorkerThreads() )
+ return MIstatus::failure;
+
+ // App is not quitting currently
+ m_bExitApp = false;
+
+ // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+#if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+ if( HaveExecutableFileNamePathOnCmdLine() )
+ {
+ if( !LocalDebugSessionStartupInjectCommands() )
+ {
+ SetErrorDescription( MIRSRC( IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION ) );
+ return MIstatus::failure;
+ }
+ }
+#endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+
+ // While the app is active
+ while( !m_bExitApp )
+ {
+ // Poll stdin queue and dispatch
+ if( !ReadStdinLineQueue() )
+ {
+ // Something went wrong
+ break;
+ }
+ }
+
+ // Signal that the application is shutting down
+ DoAppQuit();
+
+ // Close and wait for the workers to stop
+ StopWorkerThreads();
+
+ // Ensure that a new line is sent as the last act of the dying driver
+ m_rStdOut.WriteMIResponse( "\n", false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver sits and waits for input to the stdin line queue shared by *this
+// driver and the stdin monitor thread, it queues, *this reads, interprets and
+// reacts.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::ReadStdinLineQueue( void )
+{
+ // True when queue contains input
+ bool bHaveInput = false;
+
+ // Stores the current input line
+ CMIUtilString lineText;
+ {
+ // Lock while we access the queue
+ CMIUtilThreadLock lock( m_threadMutex );
+ if( !m_queueStdinLine.empty() )
+ {
+ lineText = m_queueStdinLine.front();
+ m_queueStdinLine.pop();
+ bHaveInput = !lineText.empty();
+ }
+ }
+
+ // Process while we have input
+ if( bHaveInput )
+ {
+ if( lineText == "quit" )
+ {
+ // We want to be exiting when receiving a quit command
+ m_bExitApp = true;
+ return MIstatus::success;
+ }
+
+ // Process the command
+ const bool bOk = InterpretCommand( lineText );
+
+ // Draw prompt if desired
+ if( bOk && m_rStdin.GetEnablePrompt() )
+ m_rStdOut.WriteMIResponse( m_rStdin.GetPrompt() );
+
+ // Input has been processed
+ bHaveInput = false;
+ }
+ else
+ {
+ // Give resources back to the OS
+ const std::chrono::milliseconds time( 1 );
+ std::this_thread::sleep_for( time );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set things in motion, set state etc that brings *this driver (and the
+// application) to a tidy shutdown.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoAppQuit( void )
+{
+ bool bYesQuit = true;
+
+ // Shutdown stuff, ready app for exit
+ {
+ CMIUtilThreadLock lock( m_threadMutex );
+ m_bDriverIsExiting = true;
+ }
+
+ return bYesQuit;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver passes text commands to a fall through driver is it does not
+// understand them (the LLDB driver).
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vTextLine - (R) Text data representing a possible command.
+// vwbCmdYesValid - (W) True = Command valid, false = command not handled.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InterpretCommandFallThruDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid )
+{
+ MIunused( vTextLine );
+ MIunused( vwbCmdYesValid );
+
+ // ToDo: Implement when less urgent work to be done or decide remove as not required
+ //bool bOk = MIstatus::success;
+ //bool bCmdNotUnderstood = true;
+ //if( bCmdNotUnderstood && GetEnableFallThru() )
+ //{
+ // CMIUtilString errMsg;
+ // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg );
+ // if( !bOk )
+ // {
+ // errMsg = errMsg.StripCREndOfLine();
+ // errMsg = errMsg.StripCRAll();
+ // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo();
+ // const MIchar * pName = pOtherDriver->GetDriverName().c_str();
+ // const MIchar * pId = pOtherDriver->GetDriverId().c_str();
+ // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) );
+ // m_pLog->WriteMsg( msg );
+ // }
+ //}
+ //
+ //vwbCmdYesValid = bOk;
+ //CMIUtilString strNot;
+ //if( vwbCmdYesValid)
+ // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) );
+ //const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) );
+ //m_pLog->WriteLog( msg );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Driver name.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetDriverName( void ) const
+{
+ return GetName();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the unique ID for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetDriverId( void ) const
+{
+ return GetId();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call on another driver to perform work
+// should this driver not be able to handle the client data input.
+// SetDriverToFallThruTo() specifies the fall through to driver.
+// Check the error message if the function returns a failure.
+// Type: Overridden.
+// Args: vCmd - (R) Command instruction to interpret.
+// vwErrMsg - (W) Error description on command failing.
+// Return: MIstatus::success - Command succeeded.
+// MIstatus::failure - Command failed.
+// Throws: None.
+//--
+bool CMIDriver::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg )
+{
+ bool bOk = MIstatus::success;
+
+ CMIDriverBase * pOtherDriver = GetDriverToFallThruTo();
+ if( pOtherDriver == nullptr )
+ return bOk;
+
+ return pOtherDriver->DoFallThruToAnotherDriver( vCmd, vwErrMsg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a file stream to other drivers on which *this driver
+// write's out to and they read as expected input. *this driver is passing
+// through commands to the (child) pass through assigned driver.
+// Type: Overrdidden.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriver::GetStdin( void ) const
+{
+ // Note this fn is called on CMIDriverMgr register driver so stream has to be
+ // available before *this driver has been initialized! Flaw?
+
+ // This very likely to change later to a stream that the pass thru driver
+ // will read and we write to give it 'input'
+ return stdin;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a file stream to other pass through assigned drivers
+// so they know what to write to.
+// Type: Overidden.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriver::GetStdout( void ) const
+{
+ // Note this fn is called on CMIDriverMgr register driver so stream has to be
+ // available before *this driver has been initialized! Flaw?
+
+ // Do not want to pass through driver to write to stdout
+ return NULL;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a error file stream to other pass through assigned drivers
+// so they know what to write to.
+// Type: Overidden.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriver::GetStderr( void ) const
+{
+ // Note this fn is called on CMIDriverMgr register driver so stream has to be
+ // available before *this driver has been initialized! Flaw?
+
+ // This very likely to change later to a stream that the pass thru driver
+ // will write to and *this driver reads from to pass on the CMICmnLog object
+ return stderr;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set a unique ID for *this driver. It cannot be empty.
+// Type: Overridden.
+// Args: vId - (R) Text description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::SetId( const CMIUtilString & vId )
+{
+ if( vId.empty() )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_DRIVER_ERR_ID_INVALID ), GetName().c_str(), vId.c_str() );
+ return MIstatus::failure;
+ }
+
+ m_strDriverId = vId;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the unique ID for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetId( void ) const
+{
+ return m_strDriverId;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Inject a command into the command processing system to be interpreted as a
+// command read from stdin. The text representing the command is also written
+// out to stdout as the command did not come from via stdin.
+// Type: Method.
+// Args: vMICmd - (R) Text data representing a possible command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InjectMICommand( const CMIUtilString & vMICmd )
+{
+ const bool bOk = m_rStdOut.WriteMIResponse( vMICmd );
+
+ return bOk && QueueMICommand( vMICmd );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add a new command candidate to the command queue to be processed by the
+// command system.
+// Type: Method.
+// Args: vMICmd - (R) Text data representing a possible command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::QueueMICommand( const CMIUtilString & vMICmd )
+{
+ CMIUtilThreadLock lock( m_threadMutex );
+ m_queueStdinLine.push( vMICmd );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Interpret the text data and match against current commands to see if there
+// is a match. If a match then the command is issued and actioned on. The
+// text data if not understood by *this driver is past on to the Fall Thru
+// driver.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vTextLine - (R) Text data representing a possible command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InterpretCommand( const CMIUtilString & vTextLine )
+{
+ bool bCmdYesValid = false;
+ bool bOk = InterpretCommandThisDriver( vTextLine, bCmdYesValid );
+ if( bOk && !bCmdYesValid )
+ bOk = InterpretCommandFallThruDriver( vTextLine, bCmdYesValid );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Interpret the text data and match against current commands to see if there
+// is a match. If a match then the command is issued and actioned on. If a
+// command cannot be found to match then vwbCmdYesValid is set to false and
+// nothing else is done here.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vTextLine - (R) Text data representing a possible command.
+// vwbCmdYesValid - (W) True = Command invalid, false = command acted on.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InterpretCommandThisDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid )
+{
+ vwbCmdYesValid = false;
+
+ bool bCmdNotInCmdFactor = false;
+ SMICmdData cmdData;
+ CMICmdMgr & rCmdMgr = CMICmdMgr::Instance();
+ if( !rCmdMgr.CmdInterpret( vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData ) )
+ return MIstatus::failure;
+
+ if( vwbCmdYesValid )
+ {
+ // For debugging only
+ //m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() );
+
+ return ExecuteCommand( cmdData );
+ }
+
+ // Check for escape character, may be cursor control characters
+ // This code is not necessary for application operation, just want to keep tabs on what
+ // is been given to the driver to try and intepret.
+ if( vTextLine.at( 0 ) == 27 )
+ {
+ CMIUtilString logInput( MIRSRC( IDS_STDIN_INPUT_CTRL_CHARS ) );
+ for( MIuint i = 0; i < vTextLine.length(); i++ )
+ {
+ logInput += CMIUtilString::Format( "%d ", vTextLine.at( i ) );
+ }
+ m_pLog->WriteLog( logInput );
+ return MIstatus::success;
+ }
+
+ // Write to the Log that a 'command' was not valid.
+ // Report back to the MI client via MI result record.
+ CMIUtilString strNotInCmdFactory;
+ if( bCmdNotInCmdFactor )
+ strNotInCmdFactory = CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_NOT_IN_FACTORY ), cmdData.strMiCmd.c_str() );
+ const CMIUtilString strNot( CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ) );
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str() ) );
+ const CMICmnMIValueConst vconst = CMICmnMIValueConst( msg );
+ const CMICmnMIValueResult valueResult( "msg", vconst );
+ const CMICmnMIResultRecord miResultRecord( cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult );
+ m_rStdOut.WriteMIResponse( miResultRecord.GetString() );
+
+ // Proceed to wait for or execute next command
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Having previously had the potential command validated and found valid now
+// get the command executed.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vCmdData - (RW) Command meta data.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::ExecuteCommand( const SMICmdData & vCmdData )
+{
+ CMICmdMgr & rCmdMgr = CMICmdMgr::Instance();
+ return rCmdMgr.CmdExecute( vCmdData );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the MI Driver's exit application flag. The application checks this flag
+// after every stdin line is read so the exit may not be instantaneous.
+// If vbForceExit is false the MI Driver queries its state and determines if is
+// should exit or continue operating depending on that running state.
+// This is related to the running state of the MI driver.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIDriver::SetExitApplicationFlag( const bool vbForceExit )
+{
+ if( vbForceExit )
+ {
+ CMIUtilThreadLock lock( m_threadMutex );
+ m_bExitApp = true;
+ return;
+ }
+
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ // Did we receive a SIGINT from the client during a running debug program, if
+ // so then SIGINT is not to be taken as meaning kill the MI driver application
+ // but halt the inferior program being debugged instead
+ if( m_eCurrentDriverState == eDriverState_RunningDebugging )
+ {
+ InjectMICommand( "-exec-interrupt" );
+ return;
+ }
+
+ m_bExitApp = true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the MI Driver's exit exit application flag.
+// This is related to the running state of the MI driver.
+// Type: Method.
+// Args: None.
+// Return: bool - True = MI Driver is shutting down, false = MI driver is running.
+// Throws: None.
+//--
+bool CMIDriver::GetExitApplicationFlag( void ) const
+{
+ return m_bExitApp;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the current running state of the MI Driver.
+// Type: Method.
+// Args: None.
+// Return: DriverState_e - The current running state of the application.
+// Throws: None.
+//--
+CMIDriver::DriverState_e CMIDriver::GetCurrentDriverState( void ) const
+{
+ return m_eCurrentDriverState;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the current running state of the MI Driver to running and currently not in
+// a debug session.
+// Type: Method.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Return: DriverState_e - The current running state of the application.
+// Throws: None.
+//--
+bool CMIDriver::SetDriverStateRunningNotDebugging( void )
+{
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+
+ if( m_eCurrentDriverState == eDriverState_RunningNotDebugging )
+ return MIstatus::success;
+
+ // Driver cannot be in the following states to set eDriverState_RunningNotDebugging
+ switch( m_eCurrentDriverState )
+ {
+ case eDriverState_NotRunning:
+ case eDriverState_Initialising:
+ case eDriverState_ShuttingDown:
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+ case eDriverState_RunningDebugging:
+ case eDriverState_RunningNotDebugging:
+ break;
+ case eDriverState_count:
+ default:
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ), "SetDriverStateRunningNotDebugging()" ) );
+ return MIstatus::failure;
+ }
+
+ // Driver must be in this state to set eDriverState_RunningNotDebugging
+ if( m_eCurrentDriverState != eDriverState_RunningDebugging )
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+
+ m_eCurrentDriverState = eDriverState_RunningNotDebugging;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the current running state of the MI Driver to running and currently not in
+// a debug session. The driver's state must in the state running and in a
+// debug session to set this new state.
+// Type: Method.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Return: DriverState_e - The current running state of the application.
+// Throws: None.
+//--
+bool CMIDriver::SetDriverStateRunningDebugging( void )
+{
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+
+ if( m_eCurrentDriverState == eDriverState_RunningDebugging )
+ return MIstatus::success;
+
+ // Driver cannot be in the following states to set eDriverState_RunningDebugging
+ switch( m_eCurrentDriverState )
+ {
+ case eDriverState_NotRunning:
+ case eDriverState_Initialising:
+ case eDriverState_ShuttingDown:
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+ case eDriverState_RunningDebugging:
+ case eDriverState_RunningNotDebugging:
+ break;
+ case eDriverState_count:
+ default:
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ), "SetDriverStateRunningDebugging()" ) );
+ return MIstatus::failure;
+ }
+
+ // Driver must be in this state to set eDriverState_RunningDebugging
+ if( m_eCurrentDriverState != eDriverState_RunningNotDebugging )
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+
+ m_eCurrentDriverState = eDriverState_RunningDebugging;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Prepare the client IDE so it will start working/communicating with *this MI
+// driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMIDriver::InitClientIDEToMIDriver( void ) const
+{
+ // Put other IDE init functions here
+ return InitClientIDEEclipse();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The IDE Eclipse when debugging locally expects "(gdb)\n" character
+// sequence otherwise it refuses to communicate and times out. This should be
+// sent to Eclipse before anything else.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMIDriver::InitClientIDEEclipse( void ) const
+{
+ std::cout << "(gdb)" << std::endl;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask *this driver whether it found an executable in the MI Driver's list of
+// arguments which to open and debug. If so instigate commands to set up a debug
+// session for that executable.
+// Type: Method.
+// Args: None.
+// Return: bool - True = True = Yes executable given as one of the parameters to the MI
+// Driver.
+// False = not found.
+// Throws: None.
+//--
+bool CMIDriver::HaveExecutableFileNamePathOnCmdLine( void ) const
+{
+ return m_bHaveExecutableFileNamePathOnCmdLine;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve from *this driver executable file name path to start a debug session
+// with (if present see HaveExecutableFileNamePathOnCmdLine()).
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Executeable file name path or empty string.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetExecutableFileNamePathOnCmdLine( void ) const
+{
+ return m_strCmdLineArgExecuteableFileNamePath;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Execute commands (by injecting them into the stdin line queue container) and
+// other code to set up the MI Driver such that is can take the executable
+// argument passed on the command and create a debug session for it.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMIDriver::LocalDebugSessionStartupInjectCommands( void )
+{
+ const CMIUtilString strCmd( CMIUtilString::Format( "-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str() ) );
+
+ return InjectMICommand( strCmd );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the MI Driver into "its debugging an executable passed as an argument"
+// mode as against running via a client like Eclipse.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIDriver::SetDriverDebuggingArgExecutable( void )
+{
+ m_bDriverDebuggingArgExecutable = true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the MI Driver state indicating if it is operating in "its debugging
+// an executable passed as an argument" mode as against running via a client
+// like Eclipse.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+bool CMIDriver::IsDriverDebuggingArgExecutable( void ) const
+{
+ return m_bDriverDebuggingArgExecutable;
+}
+