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