1 //===-- MICmdInterpreter.cpp ------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "MICmdInterpreter.h"
11 #include "MICmdFactory.h"
14 // Details: CMICmdInterpreter constructor.
20 CMICmdInterpreter::CMICmdInterpreter()
21 : m_rCmdFactory(CMICmdFactory::Instance()) {}
24 // Details: CMICmdInterpreter destructor.
30 CMICmdInterpreter::~CMICmdInterpreter() { Shutdown(); }
33 // Details: Initialize resources for *this Command Interpreter.
36 // Return: MIstatus::success - Functional succeeded.
37 // MIstatus::failure - Functional failed.
40 bool CMICmdInterpreter::Initialize() {
41 m_clientUsageRefCnt++;
44 return MIstatus::success;
46 m_bInitialized = true;
48 return MIstatus::success;
52 // Details: Release resources for *this Command Interpreter.
55 // Return: MIstatus::success - Functional succeeded.
56 // MIstatus::failure - Functional failed.
59 bool CMICmdInterpreter::Shutdown() {
60 if (--m_clientUsageRefCnt > 0)
61 return MIstatus::success;
64 return MIstatus::success;
66 m_bInitialized = false;
68 return MIstatus::success;
72 // Details: Establish whether the text data is an MI format type command.
74 // Args: vTextLine - (R) Text data to interpret.
75 // vwbYesValid - (W) True = MI type command, false = not
77 // vwbCmdNotInCmdFactor - (W) True = MI command not found in the
78 // command factory, false = recognised.
79 // Return: MIstatus::success - Functional succeeded.
80 // MIstatus::failure - Functional failed.
83 bool CMICmdInterpreter::ValidateIsMi(const CMIUtilString &vTextLine,
85 bool &vwbCmdNotInCmdFactor,
86 SMICmdData &rwCmdData) {
88 vwbCmdNotInCmdFactor = false;
91 if (vTextLine.empty())
92 return MIstatus::success;
94 // MI format is [cmd #]-[command name]<space>[command arg(s)]
95 // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE
96 // 5-data-evaluate-expression --thread 1 --frame 0 *(argv)
99 m_miCmdData.strMiCmd = vTextLine;
101 // The following change m_miCmdData as valid parts are identified
102 vwbYesValid = (MiHasCmdTokenEndingHyphen(vTextLine) ||
103 MiHasCmdTokenEndingAlpha(vTextLine));
104 vwbYesValid = vwbYesValid && MiHasCmd(vTextLine);
106 vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd(MiGetCmdData());
107 vwbYesValid = !vwbCmdNotInCmdFactor;
110 // Update command's meta data valid state
111 m_miCmdData.bCmdValid = vwbYesValid;
113 // Ok to return new updated command information
114 rwCmdData = MiGetCmdData();
116 return MIstatus::success;
120 // Details: Establish whether the command name entered on the stdin stream is
124 // Args: vCmd - (R) Command information structure.
125 // Return: bool - True = yes command is recognised, false = command not
129 bool CMICmdInterpreter::HasCmdFactoryGotMiCmd(const SMICmdData &vCmd) const {
130 return m_rCmdFactory.CmdExist(vCmd.strMiCmd);
134 // Details: Does the command entered match the criteria for a MI command format.
135 // The format to validate against is 'nn-' where there can be 1 to n
137 // I.e. '2-gdb-exit'.
138 // Is the execution token present? The command token is entered into
140 // command meta data structure whether correct or not for reporting or
142 // command execution purposes.
144 // Args: vTextLine - (R) Text data to interpret.
145 // Return: bool - True = yes command token present, false = command not
149 bool CMICmdInterpreter::MiHasCmdTokenEndingHyphen(
150 const CMIUtilString &vTextLine) {
151 // The hyphen is mandatory
152 const size_t nPos = vTextLine.find('-', 0);
153 if ((nPos == std::string::npos))
156 if (MiHasCmdTokenPresent(vTextLine)) {
157 const std::string strNum = vTextLine.substr(0, nPos);
158 if (!CMIUtilString(strNum).IsNumber())
161 m_miCmdData.strMiCmdToken = strNum;
164 m_miCmdData.bMIOldStyle = false;
170 // Details: Does the command entered match the criteria for a MI command format.
171 // The format to validate against is 'nnA' where there can be 1 to n
173 // 'A' represents any non numeric token. I.e. '1source .gdbinit'.
174 // Is the execution token present? The command token is entered into
176 // command meta data structure whether correct or not for reporting or
178 // command execution purposes.
180 // Args: vTextLine - (R) Text data to interpret.
181 // Return: bool - True = yes command token present, false = command not
185 bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha(
186 const CMIUtilString &vTextLine) {
187 char cChar = vTextLine[0];
189 while (::isdigit(cChar) != 0) {
190 cChar = vTextLine[++i];
192 if (::isalpha(cChar) == 0)
197 const std::string strNum = vTextLine.substr(0, i);
198 m_miCmdData.strMiCmdToken = strNum.c_str();
199 m_miCmdData.bMIOldStyle = true;
205 // Details: Does the command entered match the criteria for a MI command format.
206 // Is the command token present before the hyphen?
208 // Args: vTextLine - (R) Text data to interpret.
209 // Return: bool - True = yes command token present, false = token not present.
212 bool CMICmdInterpreter::MiHasCmdTokenPresent(const CMIUtilString &vTextLine) {
213 const size_t nPos = vTextLine.find('-', 0);
218 // Details: Does the command name entered match the criteria for a MI command
220 // Is a recognised command present? The command name is entered into
222 // command meta data structure whether correct or not for reporting or
224 // command execution purposes. Command options is present are also put
226 // command meta data structure.
228 // Args: vTextLine - (R) Command information structure.
229 // Return: bool - True = yes command name present, false = command not
233 bool CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine) {
235 if (m_miCmdData.bMIOldStyle) {
236 char cChar = vTextLine[0];
238 while (::isdigit(cChar) != 0) {
239 cChar = vTextLine[++i];
243 nPos = vTextLine.find('-', 0);
246 bool bFoundCmd = false;
247 const size_t nLen = vTextLine.length();
248 const size_t nPos2 = vTextLine.find(' ', nPos);
249 if (nPos2 != std::string::npos) {
252 const CMIUtilString cmd =
253 CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1));
257 m_miCmdData.strMiCmd = cmd;
260 m_miCmdData.strMiCmdOption =
261 CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1));
265 const CMIUtilString cmd =
266 CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1));
269 m_miCmdData.strMiCmd = cmd;
274 m_miCmdData.strMiCmdAll = vTextLine;
280 // Details: Retrieve the just entered new command from stdin. It contains the
282 // name, number and any options.
284 // Args: vTextLine - (R) Command information structure.
285 // Return: SMICmdData & - Command meta data information/result/status.
288 const SMICmdData &CMICmdInterpreter::MiGetCmdData() const {