llvm-project/lldb/tools/lldb-mi/MICmdInterpreter.cpp

303 lines
9.4 KiB
C++

//===-- MICmdInterpreter.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// In-house headers:
#include "MICmdInterpreter.h"
#include "MICmdFactory.h"
//++
//------------------------------------------------------------------------------------
// Details: CMICmdInterpreter constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdInterpreter::CMICmdInterpreter()
: m_rCmdFactory(CMICmdFactory::Instance()) {}
//++
//------------------------------------------------------------------------------------
// Details: CMICmdInterpreter destructor.
// Type: Overridable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdInterpreter::~CMICmdInterpreter() { Shutdown(); }
//++
//------------------------------------------------------------------------------------
// Details: Initialize resources for *this Command Interpreter.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdInterpreter::Initialize() {
m_clientUsageRefCnt++;
if (m_bInitialized)
return MIstatus::success;
m_bInitialized = true;
return MIstatus::success;
}
//++
//------------------------------------------------------------------------------------
// Details: Release resources for *this Command Interpreter.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdInterpreter::Shutdown() {
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
if (!m_bInitialized)
return MIstatus::success;
m_bInitialized = false;
return MIstatus::success;
}
//++
//------------------------------------------------------------------------------------
// Details: Establish whether the text data is an MI format type command.
// Type: Method.
// Args: vTextLine - (R) Text data to interpret.
// vwbYesValid - (W) True = MI type command, false = not
// recognised.
// vwbCmdNotInCmdFactor - (W) True = MI command not found in the
// command factory, false = recognised.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdInterpreter::ValidateIsMi(const CMIUtilString &vTextLine,
bool &vwbYesValid,
bool &vwbCmdNotInCmdFactor,
SMICmdData &rwCmdData) {
vwbYesValid = false;
vwbCmdNotInCmdFactor = false;
rwCmdData.Clear();
if (vTextLine.empty())
return MIstatus::success;
// MI format is [cmd #]-[command name]<space>[command arg(s)]
// i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE
// 5-data-evaluate-expression --thread 1 --frame 0 *(argv)
m_miCmdData.Clear();
m_miCmdData.strMiCmd = vTextLine;
// The following change m_miCmdData as valid parts are identified
vwbYesValid = (MiHasCmdTokenEndingHyphen(vTextLine) ||
MiHasCmdTokenEndingAlpha(vTextLine));
vwbYesValid = vwbYesValid && MiHasCmd(vTextLine);
if (vwbYesValid) {
vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd(MiGetCmdData());
vwbYesValid = !vwbCmdNotInCmdFactor;
}
// Update command's meta data valid state
m_miCmdData.bCmdValid = vwbYesValid;
// Ok to return new updated command information
rwCmdData = MiGetCmdData();
return MIstatus::success;
}
//++
//------------------------------------------------------------------------------------
// Details: Establish whether the command name entered on the stdin stream is
// recognised by
// the MI driver.
// Type: Method.
// Args: vCmd - (R) Command information structure.
// Return: bool - True = yes command is recognised, false = command not
// recognised.
// Throws: None.
//--
bool CMICmdInterpreter::HasCmdFactoryGotMiCmd(const SMICmdData &vCmd) const {
return m_rCmdFactory.CmdExist(vCmd.strMiCmd);
}
//++
//------------------------------------------------------------------------------------
// Details: Does the command entered match the criteria for a MI command format.
// The format to validate against is 'nn-' where there can be 1 to n
// digits.
// I.e. '2-gdb-exit'.
// Is the execution token present? The command token is entered into
// the
// command meta data structure whether correct or not for reporting or
// later
// command execution purposes.
// Type: Method.
// Args: vTextLine - (R) Text data to interpret.
// Return: bool - True = yes command token present, false = command not
// recognised.
// Throws: None.
//--
bool CMICmdInterpreter::MiHasCmdTokenEndingHyphen(
const CMIUtilString &vTextLine) {
// The hyphen is mandatory
const size_t nPos = vTextLine.find('-', 0);
if ((nPos == std::string::npos))
return false;
if (MiHasCmdTokenPresent(vTextLine)) {
const std::string strNum = vTextLine.substr(0, nPos);
if (!CMIUtilString(strNum).IsNumber())
return false;
m_miCmdData.strMiCmdToken = strNum;
}
m_miCmdData.bMIOldStyle = false;
return true;
}
//++
//------------------------------------------------------------------------------------
// Details: Does the command entered match the criteria for a MI command format.
// The format to validate against is 'nnA' where there can be 1 to n
// digits.
// 'A' represents any non numeric token. I.e. '1source .gdbinit'.
// Is the execution token present? The command token is entered into
// the
// command meta data structure whether correct or not for reporting or
// later
// command execution purposes.
// Type: Method.
// Args: vTextLine - (R) Text data to interpret.
// Return: bool - True = yes command token present, false = command not
// recognised.
// Throws: None.
//--
bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha(
const CMIUtilString &vTextLine) {
char cChar = vTextLine[0];
MIuint i = 0;
while (::isdigit(cChar) != 0) {
cChar = vTextLine[++i];
}
if (::isalpha(cChar) == 0)
return false;
if (i == 0)
return false;
const std::string strNum = vTextLine.substr(0, i);
m_miCmdData.strMiCmdToken = strNum.c_str();
m_miCmdData.bMIOldStyle = true;
return true;
}
//++
//------------------------------------------------------------------------------------
// Details: Does the command entered match the criteria for a MI command format.
// Is the command token present before the hyphen?
// Type: Method.
// Args: vTextLine - (R) Text data to interpret.
// Return: bool - True = yes command token present, false = token not present.
// Throws: None.
//--
bool CMICmdInterpreter::MiHasCmdTokenPresent(const CMIUtilString &vTextLine) {
const size_t nPos = vTextLine.find('-', 0);
return (nPos > 0);
}
//++
//------------------------------------------------------------------------------------
// Details: Does the command name entered match the criteria for a MI command
// format.
// Is a recognised command present? The command name is entered into
// the
// command meta data structure whether correct or not for reporting or
// later
// command execution purposes. Command options is present are also put
// into the
// command meta data structure.
// Type: Method.
// Args: vTextLine - (R) Command information structure.
// Return: bool - True = yes command name present, false = command not
// recognised.
// Throws: None.
//--
bool CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine) {
size_t nPos = 0;
if (m_miCmdData.bMIOldStyle) {
char cChar = vTextLine[0];
size_t i = 0;
while (::isdigit(cChar) != 0) {
cChar = vTextLine[++i];
}
nPos = --i;
} else {
nPos = vTextLine.find('-', 0);
}
bool bFoundCmd = false;
const size_t nLen = vTextLine.length();
const size_t nPos2 = vTextLine.find(' ', nPos);
if (nPos2 != std::string::npos) {
if (nPos2 == nLen)
return false;
const CMIUtilString cmd =
CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1));
if (cmd.empty())
return false;
m_miCmdData.strMiCmd = cmd;
if (nPos2 < nLen)
m_miCmdData.strMiCmdOption =
CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1));
bFoundCmd = true;
} else {
const CMIUtilString cmd =
CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1));
if (cmd.empty())
return false;
m_miCmdData.strMiCmd = cmd;
bFoundCmd = true;
}
if (bFoundCmd)
m_miCmdData.strMiCmdAll = vTextLine;
return bFoundCmd;
}
//++
//------------------------------------------------------------------------------------
// Details: Retrieve the just entered new command from stdin. It contains the
// command
// name, number and any options.
// Type: Method.
// Args: vTextLine - (R) Command information structure.
// Return: SMICmdData & - Command meta data information/result/status.
// Throws: None.
//--
const SMICmdData &CMICmdInterpreter::MiGetCmdData() const {
return m_miCmdData;
}