blob: 33db4b8196df55e15a52f6c0d8edaa47dac3a898 [file] [log] [blame]
//===-- MICmdInterpreter.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//++
// File: MICmdInterpreter.cpp
//
// Overview: CMICmdInterpreter implementation.
//
// Environment: Compilers: Visual C++ 12.
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
// Libraries: See MIReadmetxt.
//
// Copyright: None.
//--
// In-house headers:
#include "MICmdInterpreter.h"
#include "MICmdFactory.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdInterpreter constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdInterpreter::CMICmdInterpreter(void)
: m_rCmdFactory(CMICmdFactory::Instance())
{
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdInterpreter destructor.
// Type: Overridable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdInterpreter::~CMICmdInterpreter(void)
{
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(void)
{
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(void)
{
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 indentified
vwbYesValid = (MiHasCmdTokenEndingHypthen(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::MiHasCmdTokenEndingHypthen(const CMIUtilString &vTextLine)
{
// The hythen is mandatory
const MIint nPos = vTextLine.find("-", 0);
if ((nPos == (MIint)std::string::npos))
return false;
if (MiHasCmdTokenPresent(vTextLine))
{
const std::string strNum = vTextLine.substr(0, nPos);
if (!CMIUtilString(strNum.c_str()).IsNumber())
return false;
m_miCmdData.strMiCmdToken = strNum.c_str();
}
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)
{
MIchar 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 hypen?
// 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 MIint nPos = vTextLine.find("-", 0);
return (nPos > 0);
}
//++ ------------------------------------------------------------------------------------
// Details: Does the command name entered match the criteria for a MI command format.
// Is a recogised 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)
{
MIint nPos = 0;
if (m_miCmdData.bMIOldStyle)
{
char cChar = vTextLine[0];
MIuint i = 0;
while (::isdigit(cChar) != 0)
{
cChar = vTextLine[++i];
}
nPos = --i;
}
else
{
nPos = vTextLine.find("-", 0);
}
bool bFoundCmd = false;
const MIint nLen = vTextLine.length();
const MIint nPos2 = vTextLine.find(" ", nPos);
if (nPos2 != (MIint)std::string::npos)
{
if (nPos2 == nLen)
return false;
const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1).c_str());
if (cmd.empty())
return false;
m_miCmdData.strMiCmd = cmd;
if (nPos2 < nLen)
m_miCmdData.strMiCmdOption = CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1).c_str());
bFoundCmd = true;
}
else
{
const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1).c_str());
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(void) const
{
return m_miCmdData;
}