aboutsummaryrefslogtreecommitdiff
path: root/tools/lldb-mi/MIDriverMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lldb-mi/MIDriverMgr.cpp')
-rw-r--r--tools/lldb-mi/MIDriverMgr.cpp762
1 files changed, 762 insertions, 0 deletions
diff --git a/tools/lldb-mi/MIDriverMgr.cpp b/tools/lldb-mi/MIDriverMgr.cpp
new file mode 100644
index 000000000000..b5cb7d4b5151
--- /dev/null
+++ b/tools/lldb-mi/MIDriverMgr.cpp
@@ -0,0 +1,762 @@
+//===-- MIDriverMgr.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriverMgr.cpp
+//
+// Overview: CMIDriverMgr 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 <lldb/API/SBError.h>
+
+// In-house headers:
+#include "MIDriverMgr.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmnLogMediumFile.h"
+#include "MIDriver.h"
+#include "MIUtilTermios.h"
+#include "MICmnStreamStdout.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriverMgr constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriverMgr::CMIDriverMgr( void )
+: m_pDriverCurrent( nullptr )
+, m_bInMi2Mode( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriverMgr destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriverMgr::~CMIDriverMgr( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize *this manager.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ ClrErrorDescription();
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Note initialisation order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+
+ if( bOk )
+ {
+ MIUtilTermios::StdinTermiosSet();
+ }
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVERMGR ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unbind detach or release resources used by this server in general common
+// functionality shared between versions of any server interfaces implemented.
+// Type: Method.
+// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!).
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::Shutdown( void )
+{
+ // Do not want a ref counter because this function needs to be called how ever this
+ // application stops running
+ //if( --m_clientUsageRefCnt > 0 )
+ // return MIstatus::success;
+
+ bool vbAppExitOk = true;
+
+ ClrErrorDescription();
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ if( vbAppExitOk )
+ {
+ // The MI Driver's log updating may have been switched off switch back on to say all is ok.
+ CMICmnLog::Instance().SetEnabled( true );
+#if _DEBUG
+ CMICmnStreamStdout::Instance().Write( MIRSRC( IDE_MI_APP_EXIT_OK ) ); // Both stdout and Log
+#else
+ CMICmnLog::WriteLog( MIRSRC( IDE_MI_APP_EXIT_OK ) ); // Just to the Log
+#endif // _DEBUG
+ }
+ else
+ {
+ CMICmnLog & rAppLog = CMICmnLog::Instance();
+ if( rAppLog.GetEnabled() )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDE_MI_APP_EXIT_WITH_PROBLEM ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ) );
+ CMICmnStreamStdout::Instance().Write( msg );
+ }
+ else
+ {
+ // The MI Driver's log updating may have been switched off switch back on to say there has been problem.
+ rAppLog.SetEnabled( true );
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ) );
+ CMICmnStreamStdout::Instance().Write( msg );
+ }
+ }
+
+ m_bInitialized = false;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ UnregisterDriverAll();
+ MIUtilTermios::StdinTermiosReset();
+
+ // Note shutdown order is important here
+ MI::ModuleShutdown< CMICmnResources >( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_DRIVERMGR ), errMsg.c_str() );
+ }
+
+ return bOk;
+}
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister all the Driver registered with *this manager. The manager also
+// deletes
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::UnregisterDriverAll( void )
+{
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ IDriver * pDriver = (*it).second;
+ pDriver->DoShutdown();
+
+ // Next
+ ++it;
+ }
+
+ m_mapDriverIdToDriver.clear();
+ m_pDriverCurrent = NULL;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register a driver with *this Driver Manager. Call SetUseThisDriverToDoWork()
+// inform the manager which driver is the one to the work. The manager calls
+// the driver's init function which must be successful in order to complete the
+// registration.
+// Type: Method.
+// Args: vrDriver - (R) The driver to register.
+// vrDriverID - (R) The driver's ID to lookup by.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::RegisterDriver( const IDriver & vrDriver, const CMIUtilString & vrDriverID )
+{
+ if( HaveDriverAlready( vrDriver ) )
+ return MIstatus::success;
+
+ IDriver * pDriver = const_cast< IDriver * >( &vrDriver );
+ if( !pDriver->SetId( vrDriverID ) )
+ return MIstatus::failure;
+ if( !pDriver->DoInitialize() )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_DRIVERMGR_DRIVER_ERR_INIT ), pDriver->GetName().c_str(), vrDriverID.c_str(), pDriver->GetError().c_str() );
+ return MIstatus::failure;
+ }
+
+ MapPairDriverIdToDriver_t pr( vrDriverID, pDriver );
+ m_mapDriverIdToDriver.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Query the Driver Manager to see if *this manager has the driver already
+// registered.
+// Type: Method.
+// Args: vrDriver - (R) The driver to query.
+// Return: True - registered.
+// False - not registered.
+// Throws: None.
+//--
+bool CMIDriverMgr::HaveDriverAlready( const IDriver & vrDriver ) const
+{
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ const IDriver * pDrvr = (*it).second;
+ if( pDrvr == &vrDriver )
+ return true;
+
+ // Next
+ ++it;
+ }
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister a driver from the Driver Manager. Call the SetUseThisDriverToDoWork()
+// function to define another driver to do work if the one being unregistered did
+// the work previously.
+// Type: Method.
+// Args: vrDriver - (R) The driver to unregister.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::UnregisterDriver( const IDriver & vrDriver )
+{
+ const IDriver * pDrvr = nullptr;
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ pDrvr = (*it).second;
+ if( pDrvr == &vrDriver )
+ break;
+
+ // Next
+ ++it;
+ }
+ m_mapDriverIdToDriver.erase( it );
+
+ if( m_pDriverCurrent == pDrvr )
+ m_pDriverCurrent = nullptr;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Specify the driver to do work. The Driver Manager drives this driver. Any
+// previous driver doing work is not called anymore (so be sure the previous
+// driver is in a tidy state before stopping it working).
+// Type: Method.
+// Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::SetUseThisDriverToDoWork( const IDriver & vrADriver )
+{
+ m_pDriverCurrent = const_cast< IDriver * >( &vrADriver );
+
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_SAY_DRIVER_USING ), m_pDriverCurrent->GetName().c_str() ) );
+ m_pLog->Write( msg, CMICmnLog::eLogVerbosity_Log );
+
+ m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask *this manager which driver is currently doing the work.
+// Type: Method.
+// Args: None.
+// Return: IDriver * - Pointer to a driver, NULL if there is no current working driver.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetUseThisDriverToDoWork( void ) const
+{
+ return m_pDriverCurrent;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call this function puts *this driver to work.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::DriverMainLoop( void )
+{
+ if( m_pDriverCurrent != nullptr )
+ {
+ if( !m_pDriverCurrent->DoMainLoop() )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_MAINLOOP ), m_pDriverCurrent->GetError().c_str() ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ return MIstatus::failure;
+ }
+ }
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to resize the console window.
+// Type: Method.
+// Args: vWindowSizeWsCol - (R) New window column size.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void CMIDriverMgr::DriverResizeWindow( const uint32_t vWindowSizeWsCol )
+{
+ if( m_pDriverCurrent != nullptr )
+ return m_pDriverCurrent->DoResizeWindow( vWindowSizeWsCol );
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the current driver to validate executable command line arguments.
+// Type: Method.
+// 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) Point to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, false = continue to work.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::DriverParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ if( m_pDriverCurrent == nullptr )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ return MIstatus::failure;
+ }
+
+ const lldb::SBError error( m_pDriverCurrent->DoParseArgs( argc, argv, vpStdOut, vwbExiting ) );
+ bool bOk = !error.Fail();
+ if( !bOk )
+ {
+ CMIUtilString errMsg;
+ const MIchar * pErrorCstr = error.GetCString();
+ if( pErrorCstr != nullptr )
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_PARSE_ARGS ), m_pDriverCurrent->GetName().c_str(), pErrorCstr );
+ else
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN ), m_pDriverCurrent->GetName().c_str() );
+
+ bOk = CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the current driver's last error condition.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::DriverGetError( void ) const
+{
+ if( m_pDriverCurrent != nullptr )
+ return m_pDriverCurrent->GetError();
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return CMIUtilString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the current driver's name.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Driver name.
+// Empty string = no current working driver specified.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::DriverGetName( void ) const
+{
+ if( m_pDriverCurrent != nullptr )
+ return m_pDriverCurrent->GetName();
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return CMIUtilString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the current driver's debugger object.
+// Type: Method.
+// Args: None.
+// Return: lldb::SBDebugger * - Ptr to driver's debugger object.
+// - NULL = no current working driver specified.
+// Throws: None.
+//--
+lldb::SBDebugger * CMIDriverMgr::DriverGetTheDebugger( void )
+{
+ lldb::SBDebugger * pDebugger = nullptr;
+ if( m_pDriverCurrent != nullptr )
+ pDebugger = &m_pDriverCurrent->GetTheDebugger();
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return pDebugger;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check the arguments given on the command line. The main purpose of this
+// function is to check for the presence of the --interpreter option. Having
+// this option present tells *this manager to set the CMIDriver to do work. If
+// not use the LLDB driver. The following are options that are only handled by
+// the CMIDriverMgr are:
+// --help or -h
+// --interpreter
+// --version
+// --versionLong
+// --noLog
+// --executable
+// The above arguments are not handled by any driver object except for --executable.
+// The 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: Method.
+// 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.
+// 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.
+//--
+bool CMIDriverMgr::ParseArgs( const int argc, const char * argv[], bool & vwbExiting )
+{
+ bool bOk = MIstatus::success;
+
+ vwbExiting = false;
+
+ // Print MI application path to the Log file
+ const CMIUtilString appPath( CMIUtilString::Format( MIRSRC( IDS_MI_APP_FILEPATHNAME ), argv[ 0 ] ) );
+ bOk = m_pLog->Write( appPath, CMICmnLog::eLogVerbosity_Log );
+
+ // Print application arguments to the Log file
+ const bool bHaveArgs( argc >= 2 );
+ CMIUtilString strArgs( MIRSRC( IDS_MI_APP_ARGS ) );
+ if( !bHaveArgs )
+ {
+ strArgs += MIRSRC( IDS_WORD_NONE );
+ bOk = bOk && m_pLog->Write( strArgs, CMICmnLog::eLogVerbosity_Log );
+ }
+ else
+ {
+ for( MIint i = 1; i < argc; i++ )
+ {
+ strArgs += CMIUtilString::Format( "%d:'%s' ", i, argv[ i ] );
+ }
+ bOk = bOk && m_pLog->Write( strArgs, CMICmnLog::eLogVerbosity_Log );
+ }
+
+ // Look for the command line options
+ bool bHaveArgInterpret = false;
+ bool bHaveArgVersion = false;
+ bool bHaveArgVersionLong = false;
+ bool bHaveArgNoLog = false;
+ bool bHaveArgHelp = false;
+
+ // Hardcode the use of the MI driver
+#if MICONFIG_DEFAULT_TO_MI_DRIVER
+ bHaveArgInterpret = true;
+#endif // MICONFIG_DEFAULT_TO_MI_DRIVER
+
+ if( bHaveArgs )
+ {
+ // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
+ for( MIint i = 1; i < argc; i++ )
+ {
+ // *** Add args to help in GetHelpOnCmdLineArgOptions() ***
+ const CMIUtilString strArg( argv[ i ] );
+
+ // Argument "--executable" is also check for in CMIDriver::ParseArgs()
+ if( (0 == strArg.compare( "--interpreter" )) || // Given by the client such as Eclipse
+ (0 == strArg.compare( "--executable" )) ) // Used to specify that there is executable argument also on the command line
+ { // See fn description.
+ bHaveArgInterpret = true;
+ }
+ if( 0 == strArg.compare( "--version" ) )
+ {
+ bHaveArgVersion = true;
+ }
+ if( 0 == strArg.compare( "--versionLong" ) )
+ {
+ bHaveArgVersionLong = true;
+ }
+ if( 0 == strArg.compare( "--noLog" ) )
+ {
+ bHaveArgNoLog = true;
+ }
+ if( (0 == strArg.compare( "--help" )) || (0 == strArg.compare( "-h" )) )
+ {
+ bHaveArgHelp = true;
+ }
+ }
+ }
+
+ if( bHaveArgNoLog )
+ {
+ CMICmnLog::Instance().SetEnabled( false );
+ }
+
+ // Todo: Remove this output when MI is finished. It is temporary to persuade Ecllipse plugin to work.
+ // Eclipse reads this literally and will not work unless it gets this exact version text.
+ // Handle --version option (ignore the --interpreter option if present)
+ if( bHaveArgVersion )
+ {
+ vwbExiting = true;
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( MIRSRC( IDE_MI_VERSION_GDB ) );
+ return bOk;
+ }
+
+ // Todo: Make this the --version when the the above --version version is removed
+ // Handle --versionlong option (ignore the --interpreter option if present)
+ if( bHaveArgVersionLong )
+ {
+ vwbExiting = true;
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( GetAppVersion() );
+ return bOk;
+ }
+
+ // Both '--help' and '--intepreter' means give help for MI only. Without
+ // '--interpreter' help the LLDB driver is working and so help is for that.
+ if( bHaveArgHelp && bHaveArgInterpret )
+ {
+ vwbExiting = true;
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( GetHelpOnCmdLineArgOptions() );
+ return bOk;
+ }
+
+ // This makes the assumption that there is at least one MI compatible
+ // driver registered and one LLDB driver registerd and the CMIDriver
+ // is the first one found.
+ // ToDo: Implement a better solution that handle any order, any number
+ // of drivers. Or this 'feature' may be removed if deemed not required.
+ IDriver * pLldbDriver = GetFirstNonMIDriver();
+ IDriver * pMi2Driver = GetFirstMIDriver();
+ if( bHaveArgInterpret && (pMi2Driver != nullptr) )
+ bOk = bOk && SetUseThisDriverToDoWork( *pMi2Driver );
+ else if( pLldbDriver != nullptr )
+ bOk = bOk && SetUseThisDriverToDoWork( *pLldbDriver );
+ else
+ {
+ if( bOk )
+ {
+ vwbExiting = true;
+ const CMIUtilString msg( MIRSRC( IDS_DRIVER_ERR_NON_REGISTERED ) );
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( msg );
+ }
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return formatted application version and name information.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text data.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::GetAppVersion( void ) const
+{
+ const CMIUtilString strProj( MIRSRC( IDS_PROJNAME ) );
+ const CMIUtilString strVsn( CMIDriver::Instance().GetVersionDescription() );
+ const CMIUtilString strGdb( MIRSRC( IDE_MI_VERSION_GDB ) );
+ const CMIUtilString strVrsnInfo( CMIUtilString::Format( "%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str() ) );
+
+ return strVrsnInfo;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return formatted help information on all the MI command line options.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text data.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions( void ) const
+{
+ const CMIUtilString pHelp[] =
+ {
+ MIRSRC( IDE_MI_APP_DESCRIPTION ),
+ MIRSRC( IDE_MI_APP_INFORMATION ),
+ MIRSRC( IDE_MI_APP_ARG_USAGE ),
+ MIRSRC( IDE_MI_APP_ARG_HELP ),
+ MIRSRC( IDE_MI_APP_ARG_VERSION ),
+ MIRSRC( IDE_MI_APP_ARG_VERSION_LONG ),
+ MIRSRC( IDE_MI_APP_ARG_INTERPRETER ),
+ MIRSRC( IDE_MI_APP_ARG_EXECUTEABLE ),
+ CMIUtilString::Format( MIRSRC( IDE_MI_APP_ARG_NO_APP_LOG ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ),
+ MIRSRC( IDE_MI_APP_ARG_EXECUTABLE ),
+ MIRSRC( IDS_CMD_QUIT_HELP ),
+ MIRSRC( IDE_MI_APP_ARG_EXAMPLE )
+ };
+ const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[ 0 ];
+ CMIUtilString strHelp;
+ for( MIuint i = 0; i < nHelpItems; i++ )
+ {
+ strHelp += pHelp[ i ];
+ strHelp += "\n\n";
+ }
+
+ return strHelp;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Search the registered drivers and return the first driver which says it is
+// GDB/MI compatible i.e. the CMIDriver class.
+// Type: Method.
+// Args: None.
+// Return: IDriver * - Ptr to driver, NULL = no driver found.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstMIDriver( void ) const
+{
+ IDriver * pDriver = nullptr;
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId );
+ IDriver * pDvr = (*it).second;
+ if( pDvr->GetDriverIsGDBMICompatibleDriver() )
+ {
+ pDriver = pDvr;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return pDriver;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Search the registered drivers and return the first driver which says it is
+// not GDB/MI compatible i.e. the LLDB Driver class.
+// Type: Method.
+// Args: None.
+// Return: IDriver * - Ptr to driver, NULL = no driver found.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstNonMIDriver( void ) const
+{
+ IDriver * pDriver = nullptr;
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId );
+ IDriver * pDvr = (*it).second;
+ if( !pDvr->GetDriverIsGDBMICompatibleDriver() )
+ {
+ pDriver = pDvr;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return pDriver;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Search the registered drivers and return driver with the specified ID.
+// Type: Method.
+// Args: vrDriverId - (R) ID of a driver.
+// Return: IDriver * - Ptr to driver, NULL = no driver found.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetDriver( const CMIUtilString & vrDriverId ) const
+{
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.find( vrDriverId );
+ if( it == m_mapDriverIdToDriver.end() )
+ return nullptr;
+
+ IDriver * pDriver = (*it).second;
+
+ return pDriver;
+}
+