forked from OSchip/llvm-project
1275 lines
44 KiB
C++
1275 lines
44 KiB
C++
//===-- 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:
|
|
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:
|
|
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;
|
|
}
|
|
|