blob: f0977178145306d7f50cd0a63486b47d43f11a64 [file] [log] [blame]
//===-- MICmdCmdVar.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//++
// File: MICmdCmdVar.cpp
//
// Overview: CMICmdCmdVarCreate implementation.
// CMICmdCmdVarUpdate implementation.
// CMICmdCmdVarDelete implementation.
// CMICmdCmdVarAssign implementation.
// CMICmdCmdVarSetFormat implementation.
// CMICmdCmdVarListChildren implementation.
// CMICmdCmdVarEvaluateExpression implementation.
// CMICmdCmdVarInfoPathExpression implementation.
// CMICmdCmdVarShowAttributes 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/SBStream.h>
#include <lldb/API/SBThread.h>
// In-house headers:
#include "MICmnConfig.h"
#include "MICmdCmdVar.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueConst.h"
#include "MICmnLLDBDebugger.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmdArgContext.h"
#include "MICmdArgValNumber.h"
#include "MICmdArgValString.h"
#include "MICmdArgValThreadGrp.h"
#include "MICmdArgValOptionLong.h"
#include "MICmdArgValOptionShort.h"
#include "MICmdArgValListOfN.h"
#include "MICmnLLDBProxySBValue.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarCreate constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarCreate::CMICmdCmdVarCreate( void )
: m_nChildren( 0 )
, m_nMore( 0 )
, m_nThreadId( 0 )
, m_strType( "??" )
, m_bValid( false )
, m_constStrArgThread( "thread" )
, m_constStrArgThreadGroup( "thread-group" )
, m_constStrArgFrame( "frame" )
, m_constStrArgName( "name" )
, m_constStrArgFrameAddr( "frame-addr" )
, m_constStrArgExpression( "expression" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-create";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarCreate::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarCreate destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarCreate::~CMICmdCmdVarCreate( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarCreate::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, false, true ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFrameAddr, false, true ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpression, true, true, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarCreate::Execute( void )
{
CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame );
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
CMICMDBASE_GETOPTION( pArgFrameAddr, String, m_constStrArgFrameAddr );
CMICMDBASE_GETOPTION( pArgExpression, String, m_constStrArgExpression );
// Retrieve the --thread option's thread ID (only 1)
MIuint64 nThreadId = UINT64_MAX;
if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
return MIstatus::failure;
}
m_nThreadId = nThreadId;
// Retrieve the --frame option's number
MIuint64 nFrame = UINT64_MAX;
if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) );
return MIstatus::failure;
}
const CMICmdArgValOptionLong::VecArgObjPtr_t & rVecFrameId( pArgFrame->GetExpectedOptions() );
CMICmdArgValOptionLong::VecArgObjPtr_t::const_iterator it2 = rVecFrameId.begin();
if( it2 != rVecFrameId.end() )
{
const CMICmdArgValNumber * pOption = static_cast< CMICmdArgValNumber * >( *it2 );
nFrame = pOption->GetValue();
}
bool bAutoName = false;
const CMIUtilString strArgName;
if( pArgName->GetFound() )
{
const CMIUtilString & rArg = pArgName->GetValue();
bAutoName = (rArg == "-");
}
const CMIUtilString & rStrExpression( pArgExpression->GetValue() );
m_strExpression = rStrExpression;
CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
m_strVarName = "unnamedvariable";
if( bAutoName )
{
m_strVarName = CMIUtilString::Format( "var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet() );
CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc();
}
lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
lldb::SBThread thread = rProcess.GetThreadByIndexID( nThreadId );
lldb::SBFrame frame = thread.GetFrameAtIndex( nFrame );
lldb::SBValue value = frame.FindVariable( rStrExpression.c_str() );
if( !value.IsValid() )
value = frame.EvaluateExpression( rStrExpression.c_str() );
if( value.IsValid() )
{
m_bValid = true;
m_nChildren = value.GetNumChildren();
const MIchar * pCType = value.GetTypeName();
m_strType = (pCType != nullptr) ? pCType : m_strType;
}
if( m_bValid )
{
// This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
CMICmnLLDBDebugSessionInfoVarObj varObj( rStrExpression, m_strVarName, value );
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarCreate::Acknowledge( void )
{
if( m_bValid )
{
// MI print "%s^done,name=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%llu\",has_more=\"%u\""
const CMICmnMIValueConst miValueConst( m_strVarName );
CMICmnMIValueResult miValueResultAll( "name", miValueConst );
const CMIUtilString strNumChild( CMIUtilString::Format( "%d", m_nChildren ) );
const CMICmnMIValueConst miValueConst2( strNumChild );
miValueResultAll.Add( "numchild", miValueConst2 );
CMICmnLLDBDebugSessionInfoVarObj varObj;
const bool bOk = CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_strVarName, varObj ); MIunused( bOk );
const CMICmnMIValueConst miValueConst3( varObj.GetValueFormatted() );
miValueResultAll.Add( "value", miValueConst3 );
const CMICmnMIValueConst miValueConst4( m_strType );
miValueResultAll.Add( "type", miValueConst4 );
const CMIUtilString strThreadId( CMIUtilString::Format( "%llu", m_nThreadId ) );
const CMICmnMIValueConst miValueConst5( strThreadId );
miValueResultAll.Add( "thread-id", miValueConst5 );
const CMICmnMIValueConst miValueConst6( "0" );
miValueResultAll.Add( "has_more", miValueConst6 );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultAll );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_CREATION_FAILED ), m_strExpression.c_str() ) );
CMICmnMIValueResult miValueResult( "msg", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarCreate::CreateSelf( void )
{
return new CMICmdCmdVarCreate();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarUpdate constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarUpdate::CMICmdCmdVarUpdate( void )
: m_constStrArgPrintValues( "print-values" )
, m_constStrArgName( "name" )
, m_bValueChangedArrayType( false )
, m_bValueChangedCompositeType( false )
, m_bValueChangedNormalType( false )
, m_miValueList( true )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-update";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarUpdate::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarUpdate destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarUpdate::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, false, false ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarUpdate::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
const CMIUtilString & rVarRealName( varObj.GetNameReal() ); MIunused( rVarRealName );
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
const bool bValid = rValue.IsValid();
if( bValid && rValue.GetValueDidChange() )
{
m_bValueChangedNormalType = true;
varObj.UpdateValue();
m_strValueName = rVarObjName;
return MIstatus::success;
}
// Examine an array type variable
if( !ExamineSBValueForChange( varObj, false, m_bValueChangedArrayType ) )
return MIstatus::failure;
// Handle composite types i.e. struct or arrays
const MIuint nChildren = rValue.GetNumChildren();
for( MIuint i = 0; i < nChildren; i++ )
{
lldb::SBValue member = rValue.GetChildAtIndex( i );
if( !member.IsValid() )
continue;
const CMIUtilString varName( CMIUtilString::Format( "%s.%s", rVarObjName.c_str(), member.GetName() ) );
if( member.GetValueDidChange() )
{
// Handle composite
const CMIUtilString strValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural ) );
const CMIUtilString strInScope( member.IsInScope() ? "true" : "false" );
MIFormResponse( varName, strValue, strInScope );
m_bValueChangedCompositeType = true;
}
else
{
// Handle array of composites
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( varName, varObj ) )
{
bool bValueChanged = false;
if( ExamineSBValueForChange( varObj, true, bValueChanged ) )
{
if( bValueChanged && CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( varName, varObj ) )
{
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
const bool bValid = rValue.IsValid();
const CMIUtilString strValue( bValid ? varObj.GetValueFormatted() : "<unknown>" );
const CMIUtilString strInScope( (bValid && rValue.IsInScope()) ? "true" : "false" );
MIFormResponse( varName, strValue, strInScope );
m_bValueChangedCompositeType = true;
}
}
else
return MIstatus::failure;
}
}
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarUpdate::Acknowledge( void )
{
if( m_bValueChangedArrayType || m_bValueChangedNormalType )
{
CMICmnLLDBDebugSessionInfoVarObj varObj;
CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_strValueName, varObj );
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
const bool bValid = rValue.IsValid();
const CMIUtilString strValue( bValid ? varObj.GetValueFormatted() : "<unknown>" );
const CMIUtilString strInScope( (bValid && rValue.IsInScope()) ? "true" : "false" );
// MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
const CMICmnMIValueConst miValueConst( m_strValueName );
CMICmnMIValueResult miValueResult( "name", miValueConst );
CMICmnMIValueTuple miValueTuple( miValueResult );
const CMICmnMIValueConst miValueConst2( strValue );
CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
miValueTuple.Add( miValueResult2 );
const CMICmnMIValueConst miValueConst3( strInScope );
CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 );
miValueTuple.Add( miValueResult3 );
const CMICmnMIValueConst miValueConst4( "false" );
CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 );
miValueTuple.Add( miValueResult4 );
const CMICmnMIValueConst miValueConst5( "0" );
CMICmnMIValueResult miValueResult5( "has_more", miValueConst5 );
miValueTuple.Add( miValueResult5 );
const CMICmnMIValueList miValueList( miValueTuple );
CMICmnMIValueResult miValueResult6( "changelist", miValueList );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
else if( m_bValueChangedCompositeType )
{
// MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"},{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
CMICmnMIValueResult miValueResult6( "changelist", m_miValueList );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
m_miResultRecord = miRecordResult;
}
else
{
// MI: "%s^done,changelist=[]"
const CMICmnMIValueList miValueList( true );
CMICmnMIValueResult miValueResult6( "changelist", miValueList );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarUpdate::CreateSelf( void )
{
return new CMICmdCmdVarUpdate();
}
//++ ------------------------------------------------------------------------------------
// Details: Form the MI response for multiple variables.
// Type: Method.
// Args: vrStrVarName - (R) Session var object's name.
// vrStrValue - (R) Text version of the value held in the variable.
// vrStrScope - (R) In scope "yes" or "no".
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarUpdate::MIFormResponse( const CMIUtilString & vrStrVarName, const CMIUtilString & vrStrValue, const CMIUtilString & vrStrScope )
{
// MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
const CMICmnMIValueConst miValueConst( vrStrVarName );
CMICmnMIValueResult miValueResult( "name", miValueConst );
CMICmnMIValueTuple miValueTuple( miValueResult );
const CMICmnMIValueConst miValueConst2( vrStrValue );
CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
bool bOk = miValueTuple.Add( miValueResult2 );
const CMICmnMIValueConst miValueConst3( vrStrScope );
CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 );
bOk = bOk && miValueTuple.Add( miValueResult3 );
const CMICmnMIValueConst miValueConst4( "false" );
CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 );
bOk = bOk && miValueTuple.Add( miValueResult4 );
const CMICmnMIValueConst miValueConst5( "0" );
CMICmnMIValueResult miValueResult5( "has_more", miValueConst5 );
bOk = bOk && miValueTuple.Add( miValueResult5 );
bOk = bOk && m_miValueList.Add( miValueTuple );
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Determine if the var object is a array type variable. LLDB does not 'detect'
// a value change for some types like elements in an array so have to re-evaluate
// the expression again.
// Type: Method.
// Args: vrVarObj - (R) Session var object to examine.
// vrwbChanged - (W) True = Is an array type and it changed,
// False = Not an array type or not changed.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarUpdate::ExamineSBValueForChange( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj, const bool vbIgnoreVarType, bool & vrwbChanged )
{
vrwbChanged = false;
CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
lldb::SBThread thread = rProcess.GetSelectedThread();
if( thread.GetNumFrames() == 0 )
{
return MIstatus::success;
}
const CMIUtilString & strVarObjParentName = vrVarObj.GetVarParentName();
lldb::SBFrame frame = thread.GetSelectedFrame();
const CMIUtilString & rExpression( vrVarObj.GetNameReal() );
CMIUtilString varExpression;
if( strVarObjParentName.empty() )
{
varExpression = rExpression;
}
else
{
CMICmnLLDBDebugSessionInfoVarObj varObjParent;
if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( strVarObjParentName, varObjParent ) )
varExpression = CMIUtilString::Format( "%s.%s", varObjParent.GetNameReal().c_str(), rExpression.c_str() );
else
{
// The parent is only assigned in the CMICmdCmdVarListChildren command, we have a problem, need to investigate
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), strVarObjParentName.c_str() ) );
return MIstatus::failure;
}
}
lldb::SBValue value = frame.EvaluateExpression( varExpression.c_str() );
if( !value.IsValid() )
value = frame.FindVariable( rExpression.c_str() );
if( value.IsValid() )
{
lldb::SBType valueType = value.GetType();
const lldb::BasicType eValueType = valueType.GetBasicType();
if( vbIgnoreVarType || (eValueType != lldb::BasicType::eBasicTypeInvalid) )
{
MIuint64 nPrevValue = 0;
MIuint64 nRevaluateValue = 0;
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrVarObj.GetValue() );
if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( rValue, nPrevValue ) &&
CMICmnLLDBProxySBValue::GetValueAsUnsigned( value, nRevaluateValue ) &&
(nPrevValue != nRevaluateValue) )
{
// Have a value change so update the var object
vrwbChanged = true;
const CMICmnLLDBDebugSessionInfoVarObj varObj( rExpression, vrVarObj.GetName(), value, strVarObjParentName );
}
}
}
return MIstatus::success;
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarDelete constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarDelete::CMICmdCmdVarDelete( void )
: m_constStrArgName( "name" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-delete";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarDelete::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarDelete::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarDelete destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarDelete::~CMICmdCmdVarDelete( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarDelete::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete( rVarObjName );
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarDelete::Acknowledge( void )
{
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarDelete::CreateSelf( void )
{
return new CMICmdCmdVarDelete();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarAssign constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarAssign::CMICmdCmdVarAssign( void )
: m_bOk( true )
, m_constStrArgName( "name" )
, m_constStrArgExpression( "expression" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-assign";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarAssign::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarAssign destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarAssign::~CMICmdCmdVarAssign( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarAssign::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpression, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarAssign::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
CMICMDBASE_GETOPTION( pArgExpression, String, m_constStrArgExpression );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
const CMIUtilString & rExpression( pArgExpression->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
m_varObjName = rVarObjName;
CMIUtilString strExpression( rExpression.Trim() );
strExpression = strExpression.Trim( '"' );
lldb::SBValue & rValue( const_cast< lldb::SBValue & >( varObj.GetValue() ) );
m_bOk = rValue.SetValueFromCString( strExpression.c_str() );
if( m_bOk )
varObj.UpdateValue();
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarAssign::Acknowledge( void )
{
if( m_bOk )
{
// MI print "%s^done,value=\"%s\""
CMICmnLLDBDebugSessionInfoVarObj varObj;
CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj );
const CMICmnMIValueConst miValueConst( varObj.GetValueFormatted() );
const CMICmnMIValueResult miValueResult( "value", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
const CMICmnMIValueConst miValueConst( "expression could not be evaluated" );
const CMICmnMIValueResult miValueResult( "msg", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarAssign::CreateSelf( void )
{
return new CMICmdCmdVarAssign();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarSetFormat constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat( void )
: m_constStrArgName( "name" )
, m_constStrArgFormatSpec( "format-spec" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-set-format";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarSetFormat::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarSetFormat destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarSetFormat::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFormatSpec, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarSetFormat::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
CMICMDBASE_GETOPTION( pArgFormatSpec, String, m_constStrArgFormatSpec );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
const CMIUtilString & rExpression( pArgFormatSpec->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
if( !varObj.SetVarFormat( CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( rExpression ) ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_ENUM_INVALID ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str(), rExpression.c_str() ) );
return MIstatus::failure;
}
varObj.UpdateValue();
m_varObjName = rVarObjName;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarSetFormat::Acknowledge( void )
{
// MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
CMICmnLLDBDebugSessionInfoVarObj varObj;
CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj );
const CMICmnMIValueConst miValueConst( m_varObjName );
const CMICmnMIValueResult miValueResult( "name", miValueConst );
CMICmnMIValueTuple miValueTuple( miValueResult );
const CMICmnMIValueConst miValueConst2( varObj.GetValueFormatted() );
const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
miValueTuple.Add( miValueResult2 );
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
const CMICmnMIValueConst miValueConst3( rValue.IsInScope() ? "true" : "false" );
const CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 );
miValueTuple.Add( miValueResult3 );
const CMICmnMIValueConst miValueConst4( "false" );
const CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 );
miValueTuple.Add( miValueResult4 );
const CMICmnMIValueConst miValueConst5( "0" );
const CMICmnMIValueResult miValueResult5( "type_changed", miValueConst5 );
miValueTuple.Add( miValueResult5 );
const CMICmnMIValueList miValueList( miValueTuple );
const CMICmnMIValueResult miValueResult6( "changelist", miValueList );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarSetFormat::CreateSelf( void )
{
return new CMICmdCmdVarSetFormat();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarListChildren constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarListChildren::CMICmdCmdVarListChildren( void )
: m_bValueValid( false )
, m_nChildren( 0 )
, m_constStrArgPrintValues( "print-values" )
, m_constStrArgName( "name" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-list-children";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarListChildren::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarListChildren destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren( void )
{
m_vecMiValueResult.clear();
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarListChildren::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, false, false ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarListChildren::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
m_bValueValid = rValue.IsValid();
if( !m_bValueValid )
return MIstatus::success;
m_vecMiValueResult.clear();
m_nChildren = rValue.GetNumChildren();
for( MIuint i = 0; i < m_nChildren; i++ )
{
lldb::SBValue member = rValue.GetChildAtIndex( i );
if( !member.IsValid() )
continue;
const MIchar * pExp = member.GetName();
const CMIUtilString strExp = (pExp != nullptr) ? pExp : "??";
const CMIUtilString name( CMIUtilString::Format( "%s.%s", rVarObjName.c_str(), strExp.c_str() ) );
const MIuint nChildren = member.GetNumChildren();
const MIchar * pTypeName = member.GetType().GetName();
const CMIUtilString strType = (pTypeName != nullptr) ? pTypeName : MIRSRC( IDS_WORD_UNKNOWNTYPE_BRKTS );
const CMIUtilString strThreadId( CMIUtilString::Format( "%u", member.GetThread().GetIndexID() ) );
// Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
CMICmnLLDBDebugSessionInfoVarObj var( strExp, name, member, rVarObjName );
// MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}"
const CMICmnMIValueConst miValueConst( name );
const CMICmnMIValueResult miValueResult( "name", miValueConst );
CMICmnMIValueTuple miValueTuple( miValueResult );
const CMICmnMIValueConst miValueConst2( strExp );
const CMICmnMIValueResult miValueResult2( "exp", miValueConst2 );
miValueTuple.Add( miValueResult2 );
const CMIUtilString strNumChild( CMIUtilString::Format( "%d", nChildren ) );
const CMICmnMIValueConst miValueConst3( strNumChild );
const CMICmnMIValueResult miValueResult3( "numchild", miValueConst3 );
miValueTuple.Add( miValueResult3 );
const CMICmnMIValueConst miValueConst5( strType );
const CMICmnMIValueResult miValueResult5( "type", miValueConst5 );
miValueTuple.Add( miValueResult5 );
const CMICmnMIValueConst miValueConst6( strThreadId );
const CMICmnMIValueResult miValueResult6( "thread-id", miValueConst6 );
miValueTuple.Add( miValueResult6 );
const CMICmnMIValueConst miValueConst7( "0" );
const CMICmnMIValueResult miValueResult7( "has_more", miValueConst7 );
miValueTuple.Add( miValueResult7 );
const CMICmnMIValueResult miValueResult8( "child", miValueTuple );
m_vecMiValueResult.push_back( miValueResult8 );
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarListChildren::Acknowledge( void )
{
if( m_bValueValid )
{
// MI print "%s^done,numchild=\"%u\",children=[]""
const CMIUtilString strNumChild( CMIUtilString::Format( "%u", m_nChildren ) );
const CMICmnMIValueConst miValueConst( strNumChild );
CMICmnMIValueResult miValueResult( "numchild", miValueConst );
VecMIValueResult_t::const_iterator it = m_vecMiValueResult.begin();
if( it == m_vecMiValueResult.end() )
{
const CMICmnMIValueConst miValueConst( "[]" );
miValueResult.Add( "children", miValueConst );
}
else
{
CMICmnMIValueList miValueList( *it );
++it;
while( it != m_vecMiValueResult.end() )
{
const CMICmnMIValueResult & rResult( *it );
miValueList.Add( rResult );
// Next
++it;
}
miValueResult.Add( "children", miValueList );
}
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
// MI print "%s^done,numchild=\"0\""
const CMICmnMIValueConst miValueConst( "0" );
const CMICmnMIValueResult miValueResult( "numchild", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarListChildren::CreateSelf( void )
{
return new CMICmdCmdVarListChildren();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarEvaluateExpression constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression( void )
: m_bValueValid( true )
, m_constStrArgFormatSpec( "-f" )
, m_constStrArgName( "name" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-evaluate-expression";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarEvaluateExpression::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarEvaluateExpression destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarEvaluateExpression::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1 ) ) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarEvaluateExpression::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
m_bValueValid = rValue.IsValid();
if( !m_bValueValid )
return MIstatus::success;
m_varObjName = rVarObjName;
varObj.UpdateValue();
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarEvaluateExpression::Acknowledge( void )
{
if( m_bValueValid )
{
CMICmnLLDBDebugSessionInfoVarObj varObj;
CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj );
const CMICmnMIValueConst miValueConst( varObj.GetValueFormatted() );
const CMICmnMIValueResult miValueResult( "value", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
const CMICmnMIValueConst miValueConst( "variable invalid" );
const CMICmnMIValueResult miValueResult( "msg", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarEvaluateExpression::CreateSelf( void )
{
return new CMICmdCmdVarEvaluateExpression();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarInfoPathExpression constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression( void )
: m_bValueValid( true )
, m_constStrArgName( "name" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-info-path-expression";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarInfoPathExpression::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarInfoPathExpression destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarInfoPathExpression::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarInfoPathExpression::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
m_bValueValid = rValue.IsValid();
if( !m_bValueValid )
return MIstatus::success;
lldb::SBStream stream;
if( !rValue.GetExpressionPath( stream, true ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
const MIchar * pPathExpression = stream.GetData();
if( pPathExpression == nullptr )
{
// Build expression from what we do know
m_strPathExpression = varObj.GetNameReal();
return MIstatus::success;
}
// Has LLDB returned a var signature of it's own
if( pPathExpression[ 0 ] != '$' )
{
m_strPathExpression = pPathExpression;
return MIstatus::success;
}
// Build expression from what we do know
const CMIUtilString & rVarParentName( varObj.GetVarParentName() );
if( rVarParentName.empty() )
{
m_strPathExpression = varObj.GetNameReal();
}
else
{
CMICmnLLDBDebugSessionInfoVarObj varObjParent;
if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarParentName, varObjParent ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarParentName.c_str() ) );
return MIstatus::failure;
}
m_strPathExpression = CMIUtilString::Format( "%s.%s", varObjParent.GetNameReal().c_str(), varObj.GetNameReal().c_str() );
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarInfoPathExpression::Acknowledge( void )
{
if( m_bValueValid )
{
const CMICmnMIValueConst miValueConst( m_strPathExpression );
const CMICmnMIValueResult miValueResult( "path_expr", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
const CMICmnMIValueConst miValueConst( "variable invalid" );
const CMICmnMIValueResult miValueResult( "msg", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarInfoPathExpression::CreateSelf( void )
{
return new CMICmdCmdVarInfoPathExpression();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarShowAttributes constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes( void )
: m_constStrArgName( "name" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "var-show-attributes";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdVarShowAttributes::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdVarShowAttributes destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarShowAttributes::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarShowAttributes::Execute( void )
{
CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
const CMIUtilString & rVarObjName( pArgName->GetValue() );
CMICmnLLDBDebugSessionInfoVarObj varObj;
if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
return MIstatus::failure;
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdVarShowAttributes::Acknowledge( void )
{
// MI output: "%s^done,status=\"editable\"]"
const CMICmnMIValueConst miValueConst( "editable" );
const CMICmnMIValueResult miValueResult( "status", miValueConst );
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdVarShowAttributes::CreateSelf( void )
{
return new CMICmdCmdVarShowAttributes();
}