| //===-- 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; |
| } |