]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.cpp
Merge ^/head r352319 through r352435.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmdInterpreter.cpp
1 //===-- MICmdInterpreter.cpp ------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 // In-house headers:
10 #include "MICmdInterpreter.h"
11 #include "MICmdFactory.h"
12
13 //++
14 // Details: CMICmdInterpreter constructor.
15 // Type:    Method.
16 // Args:    None.
17 // Return:  None.
18 // Throws:  None.
19 //--
20 CMICmdInterpreter::CMICmdInterpreter()
21     : m_rCmdFactory(CMICmdFactory::Instance()) {}
22
23 //++
24 // Details: CMICmdInterpreter destructor.
25 // Type:    Overridable.
26 // Args:    None.
27 // Return:  None.
28 // Throws:  None.
29 //--
30 CMICmdInterpreter::~CMICmdInterpreter() { Shutdown(); }
31
32 //++
33 // Details: Initialize resources for *this Command Interpreter.
34 // Type:    Method.
35 // Args:    None.
36 // Return:  MIstatus::success - Functional succeeded.
37 //          MIstatus::failure - Functional failed.
38 // Throws:  None.
39 //--
40 bool CMICmdInterpreter::Initialize() {
41   m_clientUsageRefCnt++;
42
43   if (m_bInitialized)
44     return MIstatus::success;
45
46   m_bInitialized = true;
47
48   return MIstatus::success;
49 }
50
51 //++
52 // Details: Release resources for *this Command Interpreter.
53 // Type:    Method.
54 // Args:    None.
55 // Return:  MIstatus::success - Functional succeeded.
56 //          MIstatus::failure - Functional failed.
57 // Throws:  None.
58 //--
59 bool CMICmdInterpreter::Shutdown() {
60   if (--m_clientUsageRefCnt > 0)
61     return MIstatus::success;
62
63   if (!m_bInitialized)
64     return MIstatus::success;
65
66   m_bInitialized = false;
67
68   return MIstatus::success;
69 }
70
71 //++
72 // Details: Establish whether the text data is an MI format type command.
73 // Type:    Method.
74 // Args:    vTextLine               - (R) Text data to interpret.
75 //          vwbYesValid             - (W) True = MI type command, false = not
76 //          recognised.
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.
81 // Throws:  None.
82 //--
83 bool CMICmdInterpreter::ValidateIsMi(const CMIUtilString &vTextLine,
84                                      bool &vwbYesValid,
85                                      bool &vwbCmdNotInCmdFactor,
86                                      SMICmdData &rwCmdData) {
87   vwbYesValid = false;
88   vwbCmdNotInCmdFactor = false;
89   rwCmdData.Clear();
90
91   if (vTextLine.empty())
92     return MIstatus::success;
93
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)
97
98   m_miCmdData.Clear();
99   m_miCmdData.strMiCmd = vTextLine;
100
101   // The following change m_miCmdData as valid parts are identified
102   vwbYesValid = (MiHasCmdTokenEndingHyphen(vTextLine) ||
103                  MiHasCmdTokenEndingAlpha(vTextLine));
104   vwbYesValid = vwbYesValid && MiHasCmd(vTextLine);
105   if (vwbYesValid) {
106     vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd(MiGetCmdData());
107     vwbYesValid = !vwbCmdNotInCmdFactor;
108   }
109
110   // Update command's meta data valid state
111   m_miCmdData.bCmdValid = vwbYesValid;
112
113   // Ok to return new updated command information
114   rwCmdData = MiGetCmdData();
115
116   return MIstatus::success;
117 }
118
119 //++
120 // Details: Establish whether the command name entered on the stdin stream is
121 // recognised by
122 //          the MI driver.
123 // Type:    Method.
124 // Args:    vCmd    - (R) Command information structure.
125 // Return:  bool  - True = yes command is recognised, false = command not
126 // recognised.
127 // Throws:  None.
128 //--
129 bool CMICmdInterpreter::HasCmdFactoryGotMiCmd(const SMICmdData &vCmd) const {
130   return m_rCmdFactory.CmdExist(vCmd.strMiCmd);
131 }
132
133 //++
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
136 //          digits.
137 //          I.e. '2-gdb-exit'.
138 //          Is the execution token present? The command token is entered into
139 //          the
140 //          command meta data structure whether correct or not for reporting or
141 //          later
142 //          command execution purposes.
143 // Type:    Method.
144 // Args:    vTextLine   - (R) Text data to interpret.
145 // Return:  bool  - True = yes command token present, false = command not
146 // recognised.
147 // Throws:  None.
148 //--
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))
154     return false;
155
156   if (MiHasCmdTokenPresent(vTextLine)) {
157     const std::string strNum = vTextLine.substr(0, nPos);
158     if (!CMIUtilString(strNum).IsNumber())
159       return false;
160
161     m_miCmdData.strMiCmdToken = strNum;
162   }
163
164   m_miCmdData.bMIOldStyle = false;
165
166   return true;
167 }
168
169 //++
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
172 //          digits.
173 //          'A' represents any non numeric token. I.e. '1source .gdbinit'.
174 //          Is the execution token present? The command token is entered into
175 //          the
176 //          command meta data structure whether correct or not for reporting or
177 //          later
178 //          command execution purposes.
179 // Type:    Method.
180 // Args:    vTextLine   - (R) Text data to interpret.
181 // Return:  bool  - True = yes command token present, false = command not
182 // recognised.
183 // Throws:  None.
184 //--
185 bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha(
186     const CMIUtilString &vTextLine) {
187   char cChar = vTextLine[0];
188   MIuint i = 0;
189   while (::isdigit(cChar) != 0) {
190     cChar = vTextLine[++i];
191   }
192   if (::isalpha(cChar) == 0)
193     return false;
194   if (i == 0)
195     return false;
196
197   const std::string strNum = vTextLine.substr(0, i);
198   m_miCmdData.strMiCmdToken = strNum.c_str();
199   m_miCmdData.bMIOldStyle = true;
200
201   return true;
202 }
203
204 //++
205 // Details: Does the command entered match the criteria for a MI command format.
206 //          Is the command token present before the hyphen?
207 // Type:    Method.
208 // Args:    vTextLine - (R) Text data to interpret.
209 // Return:  bool  - True = yes command token present, false = token not present.
210 // Throws:  None.
211 //--
212 bool CMICmdInterpreter::MiHasCmdTokenPresent(const CMIUtilString &vTextLine) {
213   const size_t nPos = vTextLine.find('-', 0);
214   return (nPos > 0);
215 }
216
217 //++
218 // Details: Does the command name entered match the criteria for a MI command
219 // format.
220 //          Is a recognised command present? The command name is entered into
221 //          the
222 //          command meta data structure whether correct or not for reporting or
223 //          later
224 //          command execution purposes. Command options is present are also put
225 //          into the
226 //          command meta data structure.
227 // Type:    Method.
228 // Args:    vTextLine   - (R) Command information structure.
229 // Return:  bool  - True = yes command name present, false = command not
230 // recognised.
231 // Throws:  None.
232 //--
233 bool CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine) {
234   size_t nPos = 0;
235   if (m_miCmdData.bMIOldStyle) {
236     char cChar = vTextLine[0];
237     size_t i = 0;
238     while (::isdigit(cChar) != 0) {
239       cChar = vTextLine[++i];
240     }
241     nPos = --i;
242   } else {
243     nPos = vTextLine.find('-', 0);
244   }
245
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) {
250     if (nPos2 == nLen)
251       return false;
252     const CMIUtilString cmd =
253         CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1));
254     if (cmd.empty())
255       return false;
256
257     m_miCmdData.strMiCmd = cmd;
258
259     if (nPos2 < nLen)
260       m_miCmdData.strMiCmdOption =
261           CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1));
262
263     bFoundCmd = true;
264   } else {
265     const CMIUtilString cmd =
266         CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1));
267     if (cmd.empty())
268       return false;
269     m_miCmdData.strMiCmd = cmd;
270     bFoundCmd = true;
271   }
272
273   if (bFoundCmd)
274     m_miCmdData.strMiCmdAll = vTextLine;
275
276   return bFoundCmd;
277 }
278
279 //++
280 // Details: Retrieve the just entered new command from stdin. It contains the
281 // command
282 //          name, number and any options.
283 // Type:    Method.
284 // Args:    vTextLine   - (R) Command information structure.
285 // Return:  SMICmdData & - Command meta data information/result/status.
286 // Throws:  None.
287 //--
288 const SMICmdData &CMICmdInterpreter::MiGetCmdData() const {
289   return m_miCmdData;
290 }