We want to do a better job presenting errors that occur when evaluating expressions. Key to this effort is getting away from a model where all errors are spat out onto a stream where the client has to take or leave all of them. To this end, this patch adds a new class, DiagnosticManager, which contains errors produced by the compiler or by LLDB as an expression is created. The DiagnosticManager can dump itself to a log as well as to a string. Clients will (in the future) be able to filter out the errors they're interested in by ID or present subsets of these errors to the user. This patch is not intended to change the *users* of errors - only to thread DiagnosticManagers to all the places where streams are used. I also attempt to standardize our use of errors a bit, removing trailing newlines and making clients omit 'error:', 'warning:' etc. and instead pass the Severity flag. The patch is testsuite-neutral, with modifications to one part of the MI tests because it relied on "error: error:" being erroneously printed. This patch fixes the MI variable handling and the testcase. <rdar://problem/22864976> llvm-svn: 263859
1505 lines
57 KiB
C++
1505 lines
57 KiB
C++
//===-- MICmdCmdVar.cpp -----------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Overview: CMICmdCmdVarCreate implementation.
|
|
// CMICmdCmdVarUpdate implementation.
|
|
// CMICmdCmdVarDelete implementation.
|
|
// CMICmdCmdVarAssign implementation.
|
|
// CMICmdCmdVarSetFormat implementation.
|
|
// CMICmdCmdVarListChildren implementation.
|
|
// CMICmdCmdVarEvaluateExpression implementation.
|
|
// CMICmdCmdVarInfoPathExpression implementation.
|
|
// CMICmdCmdVarShowAttributes implementation.
|
|
|
|
// Third Party Headers:
|
|
#include "lldb/API/SBStream.h"
|
|
#include "lldb/API/SBType.h"
|
|
#include "lldb/API/SBThread.h"
|
|
|
|
// In-house headers:
|
|
#include "MICmdCmdVar.h"
|
|
#include "MICmnMIResultRecord.h"
|
|
#include "MICmnMIValueConst.h"
|
|
#include "MICmnLLDBDebugger.h"
|
|
#include "MICmnLLDBDebugSessionInfo.h"
|
|
#include "MICmdArgValNumber.h"
|
|
#include "MICmdArgValString.h"
|
|
#include "MICmdArgValThreadGrp.h"
|
|
#include "MICmdArgValOptionLong.h"
|
|
#include "MICmdArgValOptionShort.h"
|
|
#include "MICmdArgValPrintValues.h"
|
|
#include "MICmdArgValListOfN.h"
|
|
#include "MICmnLLDBProxySBValue.h"
|
|
#include "MICmnLLDBUtilSBValue.h"
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarCreate constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarCreate::CMICmdCmdVarCreate()
|
|
: m_nChildren(0)
|
|
, m_nThreadId(0)
|
|
, m_strType("??")
|
|
, m_bValid(false)
|
|
, m_strValue("??")
|
|
, 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, false, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFrameAddr, false, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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->GetFound() && !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;
|
|
}
|
|
|
|
// Retrieve the --frame option's number
|
|
MIuint64 nFrame = UINT64_MAX;
|
|
if (pArgThread->GetFound() && !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();
|
|
}
|
|
|
|
m_strVarName = "<unnamedvariable>";
|
|
if (pArgName->GetFound())
|
|
{
|
|
const CMIUtilString &rArg = pArgName->GetValue();
|
|
const bool bAutoName = (rArg == "-");
|
|
if (bAutoName)
|
|
{
|
|
m_strVarName = CMIUtilString::Format("var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet());
|
|
CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc();
|
|
}
|
|
else
|
|
m_strVarName = rArg;
|
|
}
|
|
|
|
bool bCurrentFrame = false;
|
|
if (pArgFrameAddr->GetFound())
|
|
{
|
|
const CMIUtilString &rStrFrameAddr(pArgFrameAddr->GetValue());
|
|
bCurrentFrame = CMIUtilString::Compare(rStrFrameAddr, "*");
|
|
if (!bCurrentFrame && (nFrame == UINT64_MAX))
|
|
{
|
|
//FIXME: *addr isn't implemented. Exit with error if --thread isn't specified.
|
|
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str()));
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
|
|
const CMIUtilString &rStrExpression(pArgExpression->GetValue());
|
|
m_strExpression = rStrExpression;
|
|
|
|
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
|
|
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
|
|
lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread();
|
|
m_nThreadId = thread.GetIndexID();
|
|
lldb::SBFrame frame = bCurrentFrame ? thread.GetSelectedFrame() : thread.GetFrameAtIndex(nFrame);
|
|
lldb::SBValue value;
|
|
|
|
if (rStrExpression[0] == '$')
|
|
{
|
|
const CMIUtilString rStrRegister(rStrExpression.substr(1));
|
|
value = frame.FindRegister(rStrRegister.c_str());
|
|
}
|
|
else
|
|
{
|
|
const bool bArgs = true;
|
|
const bool bLocals = true;
|
|
const bool bStatics = true;
|
|
const bool bInScopeOnly = false;
|
|
const lldb::SBValueList valueList = frame.GetVariables(bArgs, bLocals, bStatics, bInScopeOnly);
|
|
value = valueList.GetFirstValueByName(rStrExpression.c_str());
|
|
}
|
|
|
|
if (!value.IsValid())
|
|
value = frame.EvaluateExpression(rStrExpression.c_str());
|
|
|
|
if (value.IsValid() && value.GetError().Success())
|
|
{
|
|
CompleteSBValue(value);
|
|
m_bValid = true;
|
|
m_nChildren = value.GetNumChildren();
|
|
m_strType = CMICmnLLDBUtilSBValue(value).GetTypeNameDisplay();
|
|
|
|
// This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
|
|
CMICmnLLDBDebugSessionInfoVarObj varObj(rStrExpression, m_strVarName, value);
|
|
m_strValue = varObj.GetValueFormatted();
|
|
}
|
|
else
|
|
{
|
|
m_strValue = value.GetError().GetCString();
|
|
}
|
|
|
|
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()
|
|
{
|
|
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);
|
|
const CMICmnMIValueConst miValueConst3(m_strValue);
|
|
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;
|
|
}
|
|
|
|
CMIUtilString strErrMsg(m_strValue);
|
|
if (m_strValue.empty())
|
|
strErrMsg = CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CREATION_FAILED), m_strExpression.c_str());
|
|
const CMICmnMIValueConst miValueConst(strErrMsg.Escape(true /* vbEscapeQuotes */));
|
|
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()
|
|
{
|
|
return new CMICmdCmdVarCreate();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Complete SBValue object and its children to get SBValue::GetValueDidChange
|
|
// work.
|
|
// Type: Method.
|
|
// Args: vrwValue - (R) Value to update.
|
|
// Return: MIstatus::success - Functional succeeded.
|
|
// MIstatus::failure - Functional failed.
|
|
// Throws: None.
|
|
//--
|
|
void
|
|
CMICmdCmdVarCreate::CompleteSBValue(lldb::SBValue &vrwValue)
|
|
{
|
|
// Force a value to update
|
|
vrwValue.GetValueDidChange();
|
|
|
|
// And update its children
|
|
lldb::SBType valueType = vrwValue.GetType();
|
|
if (!valueType.IsPointerType() && !valueType.IsReferenceType())
|
|
{
|
|
const MIuint nChildren = vrwValue.GetNumChildren();
|
|
for (MIuint i = 0; i < nChildren; ++i)
|
|
{
|
|
lldb::SBValue member = vrwValue.GetChildAtIndex(i);
|
|
if (member.IsValid())
|
|
CompleteSBValue(member);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarUpdate constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarUpdate::CMICmdCmdVarUpdate()
|
|
: m_constStrArgPrintValues("print-values")
|
|
, m_constStrArgName("name")
|
|
, m_bValueChanged(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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
|
|
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
|
|
|
|
CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues;
|
|
if (pArgPrintValues->GetFound())
|
|
eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue());
|
|
|
|
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 = varObj.GetValue();
|
|
if (!ExamineSBValueForChange(rValue, m_bValueChanged))
|
|
return MIstatus::failure;
|
|
|
|
if (m_bValueChanged)
|
|
{
|
|
varObj.UpdateValue();
|
|
const bool bPrintValue((eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues) ||
|
|
(eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && rValue.GetNumChildren() == 0));
|
|
const CMIUtilString strValue(bPrintValue ? varObj.GetValueFormatted() : "");
|
|
const CMIUtilString strInScope(rValue.IsInScope() ? "true" : "false");
|
|
MIFormResponse(rVarObjName, bPrintValue ? strValue.c_str() : nullptr, strInScope);
|
|
}
|
|
|
|
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()
|
|
{
|
|
if (m_bValueChanged)
|
|
{
|
|
// MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
|
|
CMICmnMIValueResult miValueResult("changelist", m_miValueList);
|
|
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
|
|
m_miResultRecord = miRecordResult;
|
|
}
|
|
else
|
|
{
|
|
// MI print "%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;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
return new CMICmdCmdVarUpdate();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Form the MI response for multiple variables.
|
|
// Type: Method.
|
|
// Args: vrStrVarName - (R) Session var object's name.
|
|
// vpValue - (R) Text version of the value held in the variable.
|
|
// vrStrScope - (R) In scope "yes" or "no".
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
void
|
|
CMICmdCmdVarUpdate::MIFormResponse(const CMIUtilString &vrStrVarName, const char *const vpValue, const CMIUtilString &vrStrScope)
|
|
{
|
|
// MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
|
|
const CMICmnMIValueConst miValueConst(vrStrVarName);
|
|
const CMICmnMIValueResult miValueResult("name", miValueConst);
|
|
CMICmnMIValueTuple miValueTuple(miValueResult);
|
|
if (vpValue != nullptr)
|
|
{
|
|
const CMICmnMIValueConst miValueConst2(vpValue);
|
|
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
|
|
miValueTuple.Add(miValueResult2);
|
|
}
|
|
const CMICmnMIValueConst miValueConst3(vrStrScope);
|
|
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("has_more", miValueConst5);
|
|
miValueTuple.Add(miValueResult5);
|
|
m_miValueList.Add(miValueTuple);
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Determine if the var object was changed.
|
|
// Type: Method.
|
|
// Args: vrVarObj - (R) Session var object to examine.
|
|
// vrwbChanged - (W) True = The var object was changed,
|
|
// False = It was not changed.
|
|
// Return: MIstatus::success - Functional succeeded.
|
|
// MIstatus::failure - Functional failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmdCmdVarUpdate::ExamineSBValueForChange(lldb::SBValue &vrwValue, bool &vrwbChanged)
|
|
{
|
|
if (vrwValue.GetValueDidChange())
|
|
{
|
|
vrwbChanged = true;
|
|
return MIstatus::success;
|
|
}
|
|
|
|
lldb::SBType valueType = vrwValue.GetType();
|
|
if (!valueType.IsPointerType() && !valueType.IsReferenceType())
|
|
{
|
|
const MIuint nChildren = vrwValue.GetNumChildren();
|
|
for (MIuint i = 0; i < nChildren; ++i)
|
|
{
|
|
lldb::SBValue member = vrwValue.GetChildAtIndex(i);
|
|
if (!member.IsValid())
|
|
continue;
|
|
|
|
if (member.GetValueDidChange())
|
|
{
|
|
vrwbChanged = true;
|
|
return MIstatus::success;
|
|
}
|
|
else if (ExamineSBValueForChange(member, vrwbChanged) && vrwbChanged)
|
|
// Handle composite types (i.e. struct or arrays)
|
|
return MIstatus::success;
|
|
}
|
|
}
|
|
|
|
vrwbChanged = false;
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarDelete constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarDelete::CMICmdCmdVarDelete()
|
|
: 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarDelete destructor.
|
|
// Type: Overrideable.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarDelete::~CMICmdCmdVarDelete()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
return new CMICmdCmdVarDelete();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarAssign constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarAssign::CMICmdCmdVarAssign()
|
|
: 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
return new CMICmdCmdVarAssign();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarSetFormat constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat()
|
|
: 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormatSpec, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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()
|
|
{
|
|
// 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()
|
|
{
|
|
return new CMICmdCmdVarSetFormat();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarListChildren constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarListChildren::CMICmdCmdVarListChildren()
|
|
: m_constStrArgPrintValues("print-values")
|
|
, m_constStrArgName("name")
|
|
, m_constStrArgFrom("from")
|
|
, m_constStrArgTo("to")
|
|
, m_bValueValid(false)
|
|
, m_nChildren(0)
|
|
, m_miValueList(true)
|
|
, m_bHasMore(false)
|
|
{
|
|
// 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrom, false, true));
|
|
m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgTo, false, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
|
|
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
|
|
CMICMDBASE_GETOPTION(pArgFrom, Number, m_constStrArgFrom);
|
|
CMICMDBASE_GETOPTION(pArgTo, Number, m_constStrArgTo);
|
|
|
|
CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues;
|
|
if (pArgPrintValues->GetFound())
|
|
eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue());
|
|
|
|
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;
|
|
}
|
|
|
|
MIuint nFrom = 0;
|
|
MIuint nTo = UINT32_MAX;
|
|
if (pArgFrom->GetFound() && pArgTo->GetFound())
|
|
{
|
|
nFrom = pArgFrom->GetValue();
|
|
nTo = pArgTo->GetValue();
|
|
}
|
|
else if (pArgFrom->GetFound() || pArgTo->GetFound())
|
|
{
|
|
// Only from or to was specified but both are required
|
|
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID), m_cmdData.strMiCmd.c_str()));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue());
|
|
m_bValueValid = rValue.IsValid();
|
|
if (!m_bValueValid)
|
|
return MIstatus::success;
|
|
|
|
const MIuint nChildren = rValue.GetNumChildren();
|
|
m_bHasMore = nTo < nChildren;
|
|
nTo = std::min(nTo, nChildren);
|
|
m_nChildren = nFrom < nTo ? nTo - nFrom : 0;
|
|
for (MIuint i = nFrom; i < nTo; i++)
|
|
{
|
|
lldb::SBValue member = rValue.GetChildAtIndex(i);
|
|
const CMICmnLLDBUtilSBValue utilValue(member);
|
|
const CMIUtilString strExp = utilValue.GetName();
|
|
const CMIUtilString name(strExp.empty() ?
|
|
CMIUtilString::Format("%s.$%u", rVarObjName.c_str(), i) :
|
|
CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str()));
|
|
const MIuint nChildren = member.GetNumChildren();
|
|
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("%u", nChildren));
|
|
const CMICmnMIValueConst miValueConst3(strNumChild);
|
|
const CMICmnMIValueResult miValueResult3("numchild", miValueConst3);
|
|
miValueTuple.Add(miValueResult3);
|
|
const CMICmnMIValueConst miValueConst5(utilValue.GetTypeNameDisplay());
|
|
const CMICmnMIValueResult miValueResult5("type", miValueConst5);
|
|
miValueTuple.Add(miValueResult5);
|
|
const CMICmnMIValueConst miValueConst6(strThreadId);
|
|
const CMICmnMIValueResult miValueResult6("thread-id", miValueConst6);
|
|
miValueTuple.Add(miValueResult6);
|
|
// nChildren == 0 is used to check for simple values
|
|
if (eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues ||
|
|
(eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && nChildren == 0))
|
|
{
|
|
const CMIUtilString strValue(
|
|
CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural));
|
|
const CMICmnMIValueConst miValueConst7(strValue);
|
|
const CMICmnMIValueResult miValueResult7("value", miValueConst7);
|
|
miValueTuple.Add(miValueResult7);
|
|
}
|
|
const CMICmnMIValueConst miValueConst8("0");
|
|
const CMICmnMIValueResult miValueResult8("has_more", miValueConst8);
|
|
miValueTuple.Add(miValueResult8);
|
|
const CMICmnMIValueResult miValueResult9("child", miValueTuple);
|
|
m_miValueList.Add(miValueResult9);
|
|
}
|
|
|
|
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()
|
|
{
|
|
if (m_bValueValid)
|
|
{
|
|
// MI print "%s^done,numchild=\"%u\",children=[%s],has_more=\"%d\""
|
|
const CMIUtilString strNumChild(CMIUtilString::Format("%u", m_nChildren));
|
|
const CMICmnMIValueConst miValueConst(strNumChild);
|
|
CMICmnMIValueResult miValueResult("numchild", miValueConst);
|
|
if (m_nChildren != 0)
|
|
miValueResult.Add("children", m_miValueList);
|
|
const CMIUtilString strHasMore(m_bHasMore ? "1" : "0");
|
|
const CMICmnMIValueConst miValueConst2(strHasMore);
|
|
miValueResult.Add("has_more", miValueConst2);
|
|
|
|
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
|
|
m_miResultRecord = miRecordResult;
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
// MI print "%s^error,msg=\"variable invalid\""
|
|
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 *
|
|
CMICmdCmdVarListChildren::CreateSelf()
|
|
{
|
|
return new CMICmdCmdVarListChildren();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarEvaluateExpression constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression()
|
|
: 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(
|
|
new CMICmdArgValOptionShort(m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1));
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
return new CMICmdCmdVarEvaluateExpression();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarInfoPathExpression constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression()
|
|
: 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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 char *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()
|
|
{
|
|
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()
|
|
{
|
|
return new CMICmdCmdVarInfoPathExpression();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmdCmdVarShowAttributes constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes()
|
|
: 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()
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
|
|
return ParseValidateCmdOptions();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// 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()
|
|
{
|
|
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()
|
|
{
|
|
// 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()
|
|
{
|
|
return new CMICmdCmdVarShowAttributes();
|
|
}
|