//===-- 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 // 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; }