1dda28197Spatrick //===-- SBCommandInterpreter.cpp ------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/lldb-types.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
12061da546Spatrick #include "lldb/Interpreter/CommandObjectMultiword.h"
13061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
14061da546Spatrick #include "lldb/Target/Target.h"
15*f6aab3d8Srobert #include "lldb/Utility/Instrumentation.h"
16061da546Spatrick #include "lldb/Utility/Listener.h"
17061da546Spatrick 
18061da546Spatrick #include "lldb/API/SBBroadcaster.h"
19061da546Spatrick #include "lldb/API/SBCommandInterpreter.h"
20dda28197Spatrick #include "lldb/API/SBCommandInterpreterRunOptions.h"
21061da546Spatrick #include "lldb/API/SBCommandReturnObject.h"
22061da546Spatrick #include "lldb/API/SBEvent.h"
23061da546Spatrick #include "lldb/API/SBExecutionContext.h"
24061da546Spatrick #include "lldb/API/SBListener.h"
25061da546Spatrick #include "lldb/API/SBProcess.h"
26061da546Spatrick #include "lldb/API/SBStream.h"
27061da546Spatrick #include "lldb/API/SBStringList.h"
28061da546Spatrick #include "lldb/API/SBTarget.h"
29061da546Spatrick 
30061da546Spatrick #include <memory>
31*f6aab3d8Srobert #include <optional>
32061da546Spatrick 
33061da546Spatrick using namespace lldb;
34061da546Spatrick using namespace lldb_private;
35061da546Spatrick 
36061da546Spatrick class CommandPluginInterfaceImplementation : public CommandObjectParsed {
37061da546Spatrick public:
CommandPluginInterfaceImplementation(CommandInterpreter & interpreter,const char * name,lldb::SBCommandPluginInterface * backend,const char * help=nullptr,const char * syntax=nullptr,uint32_t flags=0,const char * auto_repeat_command="")38061da546Spatrick   CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,
39061da546Spatrick                                        const char *name,
40061da546Spatrick                                        lldb::SBCommandPluginInterface *backend,
41061da546Spatrick                                        const char *help = nullptr,
42061da546Spatrick                                        const char *syntax = nullptr,
43dda28197Spatrick                                        uint32_t flags = 0,
44dda28197Spatrick                                        const char *auto_repeat_command = "")
45061da546Spatrick       : CommandObjectParsed(interpreter, name, help, syntax, flags),
46dda28197Spatrick         m_backend(backend) {
47dda28197Spatrick     m_auto_repeat_command =
48dda28197Spatrick         auto_repeat_command == nullptr
49*f6aab3d8Srobert             ? std::nullopt
50*f6aab3d8Srobert             : std::optional<std::string>(auto_repeat_command);
51*f6aab3d8Srobert     // We don't know whether any given command coming from this interface takes
52*f6aab3d8Srobert     // arguments or not so here we're just disabling the basic args check.
53*f6aab3d8Srobert     CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar};
54*f6aab3d8Srobert     m_arguments.push_back({none_arg});
55dda28197Spatrick   }
56061da546Spatrick 
IsRemovable() const57061da546Spatrick   bool IsRemovable() const override { return true; }
58061da546Spatrick 
59dda28197Spatrick   /// More documentation is available in lldb::CommandObject::GetRepeatCommand,
60*f6aab3d8Srobert   /// but in short, if std::nullopt is returned, the previous command will be
61dda28197Spatrick   /// repeated, and if an empty string is returned, no commands will be
62dda28197Spatrick   /// executed.
GetRepeatCommand(Args & current_command_args,uint32_t index)63*f6aab3d8Srobert   std::optional<std::string> GetRepeatCommand(Args &current_command_args,
64dda28197Spatrick                                               uint32_t index) override {
65dda28197Spatrick     if (!m_auto_repeat_command)
66*f6aab3d8Srobert       return std::nullopt;
67dda28197Spatrick     else
68*f6aab3d8Srobert       return m_auto_repeat_command;
69dda28197Spatrick   }
70dda28197Spatrick 
71061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)72061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
73061da546Spatrick     SBCommandReturnObject sb_return(result);
74061da546Spatrick     SBCommandInterpreter sb_interpreter(&m_interpreter);
75061da546Spatrick     SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
76061da546Spatrick     bool ret = m_backend->DoExecute(
77dda28197Spatrick         debugger_sb, command.GetArgumentVector(), sb_return);
78061da546Spatrick     return ret;
79061da546Spatrick   }
80061da546Spatrick   std::shared_ptr<lldb::SBCommandPluginInterface> m_backend;
81*f6aab3d8Srobert   std::optional<std::string> m_auto_repeat_command;
82061da546Spatrick };
83061da546Spatrick 
SBCommandInterpreter(CommandInterpreter * interpreter)84061da546Spatrick SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)
85061da546Spatrick     : m_opaque_ptr(interpreter) {
86*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, interpreter);
87061da546Spatrick }
88061da546Spatrick 
SBCommandInterpreter(const SBCommandInterpreter & rhs)89061da546Spatrick SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs)
90061da546Spatrick     : m_opaque_ptr(rhs.m_opaque_ptr) {
91*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, rhs);
92061da546Spatrick }
93061da546Spatrick 
94061da546Spatrick SBCommandInterpreter::~SBCommandInterpreter() = default;
95061da546Spatrick 
96061da546Spatrick const SBCommandInterpreter &SBCommandInterpreter::
operator =(const SBCommandInterpreter & rhs)97061da546Spatrick operator=(const SBCommandInterpreter &rhs) {
98*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, rhs);
99061da546Spatrick 
100061da546Spatrick   m_opaque_ptr = rhs.m_opaque_ptr;
101*f6aab3d8Srobert   return *this;
102061da546Spatrick }
103061da546Spatrick 
IsValid() const104061da546Spatrick bool SBCommandInterpreter::IsValid() const {
105*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
106061da546Spatrick   return this->operator bool();
107061da546Spatrick }
operator bool() const108061da546Spatrick SBCommandInterpreter::operator bool() const {
109*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
110061da546Spatrick 
111061da546Spatrick   return m_opaque_ptr != nullptr;
112061da546Spatrick }
113061da546Spatrick 
CommandExists(const char * cmd)114061da546Spatrick bool SBCommandInterpreter::CommandExists(const char *cmd) {
115*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, cmd);
116061da546Spatrick 
117061da546Spatrick   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd)
118061da546Spatrick                                           : false);
119061da546Spatrick }
120061da546Spatrick 
AliasExists(const char * cmd)121061da546Spatrick bool SBCommandInterpreter::AliasExists(const char *cmd) {
122*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, cmd);
123061da546Spatrick 
124061da546Spatrick   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd)
125061da546Spatrick                                           : false);
126061da546Spatrick }
127061da546Spatrick 
IsActive()128061da546Spatrick bool SBCommandInterpreter::IsActive() {
129*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
130061da546Spatrick 
131061da546Spatrick   return (IsValid() ? m_opaque_ptr->IsActive() : false);
132061da546Spatrick }
133061da546Spatrick 
WasInterrupted() const134061da546Spatrick bool SBCommandInterpreter::WasInterrupted() const {
135*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
136061da546Spatrick 
137061da546Spatrick   return (IsValid() ? m_opaque_ptr->WasInterrupted() : false);
138061da546Spatrick }
139061da546Spatrick 
GetIOHandlerControlSequence(char ch)140061da546Spatrick const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) {
141*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, ch);
142061da546Spatrick 
143061da546Spatrick   return (IsValid()
144061da546Spatrick               ? m_opaque_ptr->GetDebugger()
145061da546Spatrick                     .GetTopIOHandlerControlSequence(ch)
146061da546Spatrick                     .GetCString()
147061da546Spatrick               : nullptr);
148061da546Spatrick }
149061da546Spatrick 
150061da546Spatrick lldb::ReturnStatus
HandleCommand(const char * command_line,SBCommandReturnObject & result,bool add_to_history)151061da546Spatrick SBCommandInterpreter::HandleCommand(const char *command_line,
152061da546Spatrick                                     SBCommandReturnObject &result,
153061da546Spatrick                                     bool add_to_history) {
154*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, command_line, result, add_to_history);
155061da546Spatrick 
156061da546Spatrick   SBExecutionContext sb_exe_ctx;
157061da546Spatrick   return HandleCommand(command_line, sb_exe_ctx, result, add_to_history);
158061da546Spatrick }
159061da546Spatrick 
HandleCommand(const char * command_line,SBExecutionContext & override_context,SBCommandReturnObject & result,bool add_to_history)160061da546Spatrick lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
161061da546Spatrick     const char *command_line, SBExecutionContext &override_context,
162061da546Spatrick     SBCommandReturnObject &result, bool add_to_history) {
163*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, command_line, override_context, result,
164*f6aab3d8Srobert                      add_to_history);
165061da546Spatrick 
166061da546Spatrick   result.Clear();
167061da546Spatrick   if (command_line && IsValid()) {
168061da546Spatrick     result.ref().SetInteractive(false);
169be691f3bSpatrick     auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo;
170be691f3bSpatrick     if (override_context.get())
171be691f3bSpatrick       m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
172be691f3bSpatrick                                   override_context.get()->Lock(true),
173be691f3bSpatrick                                   result.ref());
174be691f3bSpatrick     else
175be691f3bSpatrick       m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
176be691f3bSpatrick                                   result.ref());
177061da546Spatrick   } else {
178061da546Spatrick     result->AppendError(
179061da546Spatrick         "SBCommandInterpreter or the command line is not valid");
180061da546Spatrick   }
181061da546Spatrick 
182061da546Spatrick   return result.GetStatus();
183061da546Spatrick }
184061da546Spatrick 
HandleCommandsFromFile(lldb::SBFileSpec & file,lldb::SBExecutionContext & override_context,lldb::SBCommandInterpreterRunOptions & options,lldb::SBCommandReturnObject result)185061da546Spatrick void SBCommandInterpreter::HandleCommandsFromFile(
186061da546Spatrick     lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context,
187061da546Spatrick     lldb::SBCommandInterpreterRunOptions &options,
188061da546Spatrick     lldb::SBCommandReturnObject result) {
189*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, file, override_context, options, result);
190061da546Spatrick 
191061da546Spatrick   if (!IsValid()) {
192061da546Spatrick     result->AppendError("SBCommandInterpreter is not valid.");
193061da546Spatrick     return;
194061da546Spatrick   }
195061da546Spatrick 
196061da546Spatrick   if (!file.IsValid()) {
197061da546Spatrick     SBStream s;
198061da546Spatrick     file.GetDescription(s);
199061da546Spatrick     result->AppendErrorWithFormat("File is not valid: %s.", s.GetData());
200061da546Spatrick   }
201061da546Spatrick 
202061da546Spatrick   FileSpec tmp_spec = file.ref();
203be691f3bSpatrick   if (override_context.get())
204be691f3bSpatrick     m_opaque_ptr->HandleCommandsFromFile(tmp_spec,
205be691f3bSpatrick                                          override_context.get()->Lock(true),
206be691f3bSpatrick                                          options.ref(),
207061da546Spatrick                                          result.ref());
208be691f3bSpatrick 
209be691f3bSpatrick   else
210be691f3bSpatrick     m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref());
211061da546Spatrick }
212061da546Spatrick 
HandleCompletion(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,SBStringList & matches)213061da546Spatrick int SBCommandInterpreter::HandleCompletion(
214061da546Spatrick     const char *current_line, const char *cursor, const char *last_char,
215061da546Spatrick     int match_start_point, int max_return_elements, SBStringList &matches) {
216*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point,
217061da546Spatrick                      max_return_elements, matches);
218061da546Spatrick 
219061da546Spatrick   SBStringList dummy_descriptions;
220061da546Spatrick   return HandleCompletionWithDescriptions(
221061da546Spatrick       current_line, cursor, last_char, match_start_point, max_return_elements,
222061da546Spatrick       matches, dummy_descriptions);
223061da546Spatrick }
224061da546Spatrick 
HandleCompletionWithDescriptions(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,SBStringList & matches,SBStringList & descriptions)225061da546Spatrick int SBCommandInterpreter::HandleCompletionWithDescriptions(
226061da546Spatrick     const char *current_line, const char *cursor, const char *last_char,
227061da546Spatrick     int match_start_point, int max_return_elements, SBStringList &matches,
228061da546Spatrick     SBStringList &descriptions) {
229*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point,
230061da546Spatrick                      max_return_elements, matches, descriptions);
231061da546Spatrick 
232061da546Spatrick   // Sanity check the arguments that are passed in: cursor & last_char have to
233061da546Spatrick   // be within the current_line.
234061da546Spatrick   if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
235061da546Spatrick     return 0;
236061da546Spatrick 
237061da546Spatrick   if (cursor < current_line || last_char < current_line)
238061da546Spatrick     return 0;
239061da546Spatrick 
240061da546Spatrick   size_t current_line_size = strlen(current_line);
241061da546Spatrick   if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||
242061da546Spatrick       last_char - current_line > static_cast<ptrdiff_t>(current_line_size))
243061da546Spatrick     return 0;
244061da546Spatrick 
245061da546Spatrick   if (!IsValid())
246061da546Spatrick     return 0;
247061da546Spatrick 
248061da546Spatrick   lldb_private::StringList lldb_matches, lldb_descriptions;
249061da546Spatrick   CompletionResult result;
250061da546Spatrick   CompletionRequest request(current_line, cursor - current_line, result);
251061da546Spatrick   m_opaque_ptr->HandleCompletion(request);
252061da546Spatrick   result.GetMatches(lldb_matches);
253061da546Spatrick   result.GetDescriptions(lldb_descriptions);
254061da546Spatrick 
255061da546Spatrick   // Make the result array indexed from 1 again by adding the 'common prefix'
256061da546Spatrick   // of all completions as element 0. This is done to emulate the old API.
257061da546Spatrick   if (request.GetParsedLine().GetArgumentCount() == 0) {
258061da546Spatrick     // If we got an empty string, insert nothing.
259061da546Spatrick     lldb_matches.InsertStringAtIndex(0, "");
260061da546Spatrick     lldb_descriptions.InsertStringAtIndex(0, "");
261061da546Spatrick   } else {
262061da546Spatrick     // Now figure out if there is a common substring, and if so put that in
263061da546Spatrick     // element 0, otherwise put an empty string in element 0.
264061da546Spatrick     std::string command_partial_str = request.GetCursorArgumentPrefix().str();
265061da546Spatrick 
266061da546Spatrick     std::string common_prefix = lldb_matches.LongestCommonPrefix();
267061da546Spatrick     const size_t partial_name_len = command_partial_str.size();
268061da546Spatrick     common_prefix.erase(0, partial_name_len);
269061da546Spatrick 
270061da546Spatrick     // If we matched a unique single command, add a space... Only do this if
271061da546Spatrick     // the completer told us this was a complete word, however...
272061da546Spatrick     if (lldb_matches.GetSize() == 1) {
273061da546Spatrick       char quote_char = request.GetParsedArg().GetQuoteChar();
274061da546Spatrick       common_prefix =
275061da546Spatrick           Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
276061da546Spatrick       if (request.GetParsedArg().IsQuoted())
277061da546Spatrick         common_prefix.push_back(quote_char);
278061da546Spatrick       common_prefix.push_back(' ');
279061da546Spatrick     }
280061da546Spatrick     lldb_matches.InsertStringAtIndex(0, common_prefix.c_str());
281061da546Spatrick     lldb_descriptions.InsertStringAtIndex(0, "");
282061da546Spatrick   }
283061da546Spatrick 
284061da546Spatrick   SBStringList temp_matches_list(&lldb_matches);
285061da546Spatrick   matches.AppendList(temp_matches_list);
286061da546Spatrick   SBStringList temp_descriptions_list(&lldb_descriptions);
287061da546Spatrick   descriptions.AppendList(temp_descriptions_list);
288061da546Spatrick   return result.GetNumberOfResults();
289061da546Spatrick }
290061da546Spatrick 
HandleCompletionWithDescriptions(const char * current_line,uint32_t cursor_pos,int match_start_point,int max_return_elements,SBStringList & matches,SBStringList & descriptions)291061da546Spatrick int SBCommandInterpreter::HandleCompletionWithDescriptions(
292061da546Spatrick     const char *current_line, uint32_t cursor_pos, int match_start_point,
293061da546Spatrick     int max_return_elements, SBStringList &matches,
294061da546Spatrick     SBStringList &descriptions) {
295*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point,
296061da546Spatrick                      max_return_elements, matches, descriptions);
297061da546Spatrick 
298061da546Spatrick   const char *cursor = current_line + cursor_pos;
299061da546Spatrick   const char *last_char = current_line + strlen(current_line);
300061da546Spatrick   return HandleCompletionWithDescriptions(
301061da546Spatrick       current_line, cursor, last_char, match_start_point, max_return_elements,
302061da546Spatrick       matches, descriptions);
303061da546Spatrick }
304061da546Spatrick 
HandleCompletion(const char * current_line,uint32_t cursor_pos,int match_start_point,int max_return_elements,lldb::SBStringList & matches)305061da546Spatrick int SBCommandInterpreter::HandleCompletion(const char *current_line,
306061da546Spatrick                                            uint32_t cursor_pos,
307061da546Spatrick                                            int match_start_point,
308061da546Spatrick                                            int max_return_elements,
309061da546Spatrick                                            lldb::SBStringList &matches) {
310*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point,
311061da546Spatrick                      max_return_elements, matches);
312061da546Spatrick 
313061da546Spatrick   const char *cursor = current_line + cursor_pos;
314061da546Spatrick   const char *last_char = current_line + strlen(current_line);
315061da546Spatrick   return HandleCompletion(current_line, cursor, last_char, match_start_point,
316061da546Spatrick                           max_return_elements, matches);
317061da546Spatrick }
318061da546Spatrick 
HasCommands()319061da546Spatrick bool SBCommandInterpreter::HasCommands() {
320*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
321061da546Spatrick 
322061da546Spatrick   return (IsValid() ? m_opaque_ptr->HasCommands() : false);
323061da546Spatrick }
324061da546Spatrick 
HasAliases()325061da546Spatrick bool SBCommandInterpreter::HasAliases() {
326*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
327061da546Spatrick 
328061da546Spatrick   return (IsValid() ? m_opaque_ptr->HasAliases() : false);
329061da546Spatrick }
330061da546Spatrick 
HasAliasOptions()331061da546Spatrick bool SBCommandInterpreter::HasAliasOptions() {
332*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
333061da546Spatrick 
334061da546Spatrick   return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);
335061da546Spatrick }
336061da546Spatrick 
IsInteractive()337*f6aab3d8Srobert bool SBCommandInterpreter::IsInteractive() {
338*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
339*f6aab3d8Srobert 
340*f6aab3d8Srobert   return (IsValid() ? m_opaque_ptr->IsInteractive() : false);
341*f6aab3d8Srobert }
342*f6aab3d8Srobert 
GetProcess()343061da546Spatrick SBProcess SBCommandInterpreter::GetProcess() {
344*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
345061da546Spatrick 
346061da546Spatrick   SBProcess sb_process;
347061da546Spatrick   ProcessSP process_sp;
348061da546Spatrick   if (IsValid()) {
349061da546Spatrick     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
350061da546Spatrick     if (target_sp) {
351061da546Spatrick       std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
352061da546Spatrick       process_sp = target_sp->GetProcessSP();
353061da546Spatrick       sb_process.SetSP(process_sp);
354061da546Spatrick     }
355061da546Spatrick   }
356061da546Spatrick 
357*f6aab3d8Srobert   return sb_process;
358061da546Spatrick }
359061da546Spatrick 
GetDebugger()360061da546Spatrick SBDebugger SBCommandInterpreter::GetDebugger() {
361*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
362061da546Spatrick 
363061da546Spatrick   SBDebugger sb_debugger;
364061da546Spatrick   if (IsValid())
365061da546Spatrick     sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
366061da546Spatrick 
367*f6aab3d8Srobert   return sb_debugger;
368061da546Spatrick }
369061da546Spatrick 
GetPromptOnQuit()370061da546Spatrick bool SBCommandInterpreter::GetPromptOnQuit() {
371*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
372061da546Spatrick 
373061da546Spatrick   return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);
374061da546Spatrick }
375061da546Spatrick 
SetPromptOnQuit(bool b)376061da546Spatrick void SBCommandInterpreter::SetPromptOnQuit(bool b) {
377*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, b);
378061da546Spatrick 
379061da546Spatrick   if (IsValid())
380061da546Spatrick     m_opaque_ptr->SetPromptOnQuit(b);
381061da546Spatrick }
382061da546Spatrick 
AllowExitCodeOnQuit(bool allow)383061da546Spatrick void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
384*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, allow);
385061da546Spatrick 
386061da546Spatrick   if (m_opaque_ptr)
387061da546Spatrick     m_opaque_ptr->AllowExitCodeOnQuit(allow);
388061da546Spatrick }
389061da546Spatrick 
HasCustomQuitExitCode()390061da546Spatrick bool SBCommandInterpreter::HasCustomQuitExitCode() {
391*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
392061da546Spatrick 
393061da546Spatrick   bool exited = false;
394061da546Spatrick   if (m_opaque_ptr)
395061da546Spatrick     m_opaque_ptr->GetQuitExitCode(exited);
396061da546Spatrick   return exited;
397061da546Spatrick }
398061da546Spatrick 
GetQuitStatus()399061da546Spatrick int SBCommandInterpreter::GetQuitStatus() {
400*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
401061da546Spatrick 
402061da546Spatrick   bool exited = false;
403061da546Spatrick   return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
404061da546Spatrick }
405061da546Spatrick 
ResolveCommand(const char * command_line,SBCommandReturnObject & result)406061da546Spatrick void SBCommandInterpreter::ResolveCommand(const char *command_line,
407061da546Spatrick                                           SBCommandReturnObject &result) {
408*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, command_line, result);
409061da546Spatrick 
410061da546Spatrick   result.Clear();
411061da546Spatrick   if (command_line && IsValid()) {
412061da546Spatrick     m_opaque_ptr->ResolveCommand(command_line, result.ref());
413061da546Spatrick   } else {
414061da546Spatrick     result->AppendError(
415061da546Spatrick         "SBCommandInterpreter or the command line is not valid");
416061da546Spatrick   }
417061da546Spatrick }
418061da546Spatrick 
get()419061da546Spatrick CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; }
420061da546Spatrick 
ref()421061da546Spatrick CommandInterpreter &SBCommandInterpreter::ref() {
422061da546Spatrick   assert(m_opaque_ptr);
423061da546Spatrick   return *m_opaque_ptr;
424061da546Spatrick }
425061da546Spatrick 
reset(lldb_private::CommandInterpreter * interpreter)426061da546Spatrick void SBCommandInterpreter::reset(
427061da546Spatrick     lldb_private::CommandInterpreter *interpreter) {
428061da546Spatrick   m_opaque_ptr = interpreter;
429061da546Spatrick }
430061da546Spatrick 
SourceInitFileInGlobalDirectory(SBCommandReturnObject & result)431*f6aab3d8Srobert void SBCommandInterpreter::SourceInitFileInGlobalDirectory(
432061da546Spatrick     SBCommandReturnObject &result) {
433*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, result);
434061da546Spatrick 
435061da546Spatrick   result.Clear();
436061da546Spatrick   if (IsValid()) {
437061da546Spatrick     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
438061da546Spatrick     std::unique_lock<std::recursive_mutex> lock;
439061da546Spatrick     if (target_sp)
440061da546Spatrick       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
441*f6aab3d8Srobert     m_opaque_ptr->SourceInitFileGlobal(result.ref());
442061da546Spatrick   } else {
443061da546Spatrick     result->AppendError("SBCommandInterpreter is not valid");
444be691f3bSpatrick   }
445be691f3bSpatrick }
446be691f3bSpatrick 
SourceInitFileInHomeDirectory(SBCommandReturnObject & result)447be691f3bSpatrick void SBCommandInterpreter::SourceInitFileInHomeDirectory(
448*f6aab3d8Srobert     SBCommandReturnObject &result) {
449*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, result);
450*f6aab3d8Srobert 
451*f6aab3d8Srobert   SourceInitFileInHomeDirectory(result, /*is_repl=*/false);
452*f6aab3d8Srobert }
453*f6aab3d8Srobert 
SourceInitFileInHomeDirectory(SBCommandReturnObject & result,bool is_repl)454*f6aab3d8Srobert void SBCommandInterpreter::SourceInitFileInHomeDirectory(
455be691f3bSpatrick     SBCommandReturnObject &result, bool is_repl) {
456*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, result, is_repl);
457be691f3bSpatrick 
458be691f3bSpatrick   result.Clear();
459be691f3bSpatrick   if (IsValid()) {
460be691f3bSpatrick     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
461be691f3bSpatrick     std::unique_lock<std::recursive_mutex> lock;
462be691f3bSpatrick     if (target_sp)
463be691f3bSpatrick       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
464be691f3bSpatrick     m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl);
465be691f3bSpatrick   } else {
466be691f3bSpatrick     result->AppendError("SBCommandInterpreter is not valid");
467061da546Spatrick   }
468061da546Spatrick }
469061da546Spatrick 
SourceInitFileInCurrentWorkingDirectory(SBCommandReturnObject & result)470061da546Spatrick void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
471061da546Spatrick     SBCommandReturnObject &result) {
472*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, result);
473061da546Spatrick 
474061da546Spatrick   result.Clear();
475061da546Spatrick   if (IsValid()) {
476061da546Spatrick     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
477061da546Spatrick     std::unique_lock<std::recursive_mutex> lock;
478061da546Spatrick     if (target_sp)
479061da546Spatrick       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
480061da546Spatrick     m_opaque_ptr->SourceInitFileCwd(result.ref());
481061da546Spatrick   } else {
482061da546Spatrick     result->AppendError("SBCommandInterpreter is not valid");
483061da546Spatrick   }
484061da546Spatrick }
485061da546Spatrick 
GetBroadcaster()486061da546Spatrick SBBroadcaster SBCommandInterpreter::GetBroadcaster() {
487*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
488061da546Spatrick 
489061da546Spatrick   SBBroadcaster broadcaster(m_opaque_ptr, false);
490061da546Spatrick 
491*f6aab3d8Srobert   return broadcaster;
492061da546Spatrick }
493061da546Spatrick 
GetBroadcasterClass()494061da546Spatrick const char *SBCommandInterpreter::GetBroadcasterClass() {
495*f6aab3d8Srobert   LLDB_INSTRUMENT();
496061da546Spatrick 
497061da546Spatrick   return CommandInterpreter::GetStaticBroadcasterClass().AsCString();
498061da546Spatrick }
499061da546Spatrick 
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type)500061da546Spatrick const char *SBCommandInterpreter::GetArgumentTypeAsCString(
501061da546Spatrick     const lldb::CommandArgumentType arg_type) {
502*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(arg_type);
503061da546Spatrick 
504061da546Spatrick   return CommandObject::GetArgumentTypeAsCString(arg_type);
505061da546Spatrick }
506061da546Spatrick 
GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type)507061da546Spatrick const char *SBCommandInterpreter::GetArgumentDescriptionAsCString(
508061da546Spatrick     const lldb::CommandArgumentType arg_type) {
509*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(arg_type);
510061da546Spatrick 
511061da546Spatrick   return CommandObject::GetArgumentDescriptionAsCString(arg_type);
512061da546Spatrick }
513061da546Spatrick 
EventIsCommandInterpreterEvent(const lldb::SBEvent & event)514061da546Spatrick bool SBCommandInterpreter::EventIsCommandInterpreterEvent(
515061da546Spatrick     const lldb::SBEvent &event) {
516*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(event);
517061da546Spatrick 
518061da546Spatrick   return event.GetBroadcasterClass() ==
519061da546Spatrick          SBCommandInterpreter::GetBroadcasterClass();
520061da546Spatrick }
521061da546Spatrick 
SetCommandOverrideCallback(const char * command_name,lldb::CommandOverrideCallback callback,void * baton)522061da546Spatrick bool SBCommandInterpreter::SetCommandOverrideCallback(
523061da546Spatrick     const char *command_name, lldb::CommandOverrideCallback callback,
524061da546Spatrick     void *baton) {
525*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, command_name, callback, baton);
526061da546Spatrick 
527061da546Spatrick   if (command_name && command_name[0] && IsValid()) {
528061da546Spatrick     llvm::StringRef command_name_str = command_name;
529061da546Spatrick     CommandObject *cmd_obj =
530061da546Spatrick         m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
531061da546Spatrick     if (cmd_obj) {
532061da546Spatrick       assert(command_name_str.empty());
533061da546Spatrick       cmd_obj->SetOverrideCallback(callback, baton);
534061da546Spatrick       return true;
535061da546Spatrick     }
536061da546Spatrick   }
537061da546Spatrick   return false;
538061da546Spatrick }
539061da546Spatrick 
AddMultiwordCommand(const char * name,const char * help)540061da546Spatrick lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name,
541061da546Spatrick                                                           const char *help) {
542*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, help);
543061da546Spatrick 
544*f6aab3d8Srobert   lldb::CommandObjectSP new_command_sp(
545*f6aab3d8Srobert       new CommandObjectMultiword(*m_opaque_ptr, name, help));
546*f6aab3d8Srobert   new_command_sp->GetAsMultiwordCommand()->SetRemovable(true);
547*f6aab3d8Srobert   Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);
548*f6aab3d8Srobert   if (add_error.Success())
549*f6aab3d8Srobert     return lldb::SBCommand(new_command_sp);
550*f6aab3d8Srobert   return lldb::SBCommand();
551061da546Spatrick }
552061da546Spatrick 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help)553061da546Spatrick lldb::SBCommand SBCommandInterpreter::AddCommand(
554061da546Spatrick     const char *name, lldb::SBCommandPluginInterface *impl, const char *help) {
555*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, impl, help);
556061da546Spatrick 
557*f6aab3d8Srobert   return AddCommand(name, impl, help, /*syntax=*/nullptr,
558*f6aab3d8Srobert                     /*auto_repeat_command=*/"");
559061da546Spatrick }
560061da546Spatrick 
561061da546Spatrick lldb::SBCommand
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax)562061da546Spatrick SBCommandInterpreter::AddCommand(const char *name,
563061da546Spatrick                                  lldb::SBCommandPluginInterface *impl,
564061da546Spatrick                                  const char *help, const char *syntax) {
565*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax);
566*f6aab3d8Srobert   return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/"");
567dda28197Spatrick }
568dda28197Spatrick 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax,const char * auto_repeat_command)569dda28197Spatrick lldb::SBCommand SBCommandInterpreter::AddCommand(
570dda28197Spatrick     const char *name, lldb::SBCommandPluginInterface *impl, const char *help,
571dda28197Spatrick     const char *syntax, const char *auto_repeat_command) {
572*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command);
573061da546Spatrick 
574061da546Spatrick   lldb::CommandObjectSP new_command_sp;
575061da546Spatrick   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
576dda28197Spatrick       *m_opaque_ptr, name, impl, help, syntax, /*flags=*/0,
577dda28197Spatrick       auto_repeat_command);
578061da546Spatrick 
579*f6aab3d8Srobert   Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);
580*f6aab3d8Srobert   if (add_error.Success())
581*f6aab3d8Srobert     return lldb::SBCommand(new_command_sp);
582*f6aab3d8Srobert   return lldb::SBCommand();
583061da546Spatrick }
584061da546Spatrick 
SBCommand()585*f6aab3d8Srobert SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); }
586061da546Spatrick 
SBCommand(lldb::CommandObjectSP cmd_sp)587061da546Spatrick SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {}
588061da546Spatrick 
IsValid()589061da546Spatrick bool SBCommand::IsValid() {
590*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
591061da546Spatrick   return this->operator bool();
592061da546Spatrick }
operator bool() const593061da546Spatrick SBCommand::operator bool() const {
594*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
595061da546Spatrick 
596061da546Spatrick   return m_opaque_sp.get() != nullptr;
597061da546Spatrick }
598061da546Spatrick 
GetName()599061da546Spatrick const char *SBCommand::GetName() {
600*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
601061da546Spatrick 
602061da546Spatrick   return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr);
603061da546Spatrick }
604061da546Spatrick 
GetHelp()605061da546Spatrick const char *SBCommand::GetHelp() {
606*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
607061da546Spatrick 
608061da546Spatrick   return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString()
609061da546Spatrick                     : nullptr);
610061da546Spatrick }
611061da546Spatrick 
GetHelpLong()612061da546Spatrick const char *SBCommand::GetHelpLong() {
613*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
614061da546Spatrick 
615061da546Spatrick   return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString()
616061da546Spatrick                     : nullptr);
617061da546Spatrick }
618061da546Spatrick 
SetHelp(const char * help)619061da546Spatrick void SBCommand::SetHelp(const char *help) {
620*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, help);
621061da546Spatrick 
622061da546Spatrick   if (IsValid())
623061da546Spatrick     m_opaque_sp->SetHelp(help);
624061da546Spatrick }
625061da546Spatrick 
SetHelpLong(const char * help)626061da546Spatrick void SBCommand::SetHelpLong(const char *help) {
627*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, help);
628061da546Spatrick 
629061da546Spatrick   if (IsValid())
630061da546Spatrick     m_opaque_sp->SetHelpLong(help);
631061da546Spatrick }
632061da546Spatrick 
AddMultiwordCommand(const char * name,const char * help)633061da546Spatrick lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name,
634061da546Spatrick                                                const char *help) {
635*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, help);
636061da546Spatrick 
637061da546Spatrick   if (!IsValid())
638*f6aab3d8Srobert     return lldb::SBCommand();
639061da546Spatrick   if (!m_opaque_sp->IsMultiwordObject())
640*f6aab3d8Srobert     return lldb::SBCommand();
641061da546Spatrick   CommandObjectMultiword *new_command = new CommandObjectMultiword(
642061da546Spatrick       m_opaque_sp->GetCommandInterpreter(), name, help);
643061da546Spatrick   new_command->SetRemovable(true);
644061da546Spatrick   lldb::CommandObjectSP new_command_sp(new_command);
645061da546Spatrick   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
646*f6aab3d8Srobert     return lldb::SBCommand(new_command_sp);
647*f6aab3d8Srobert   return lldb::SBCommand();
648061da546Spatrick }
649061da546Spatrick 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help)650061da546Spatrick lldb::SBCommand SBCommand::AddCommand(const char *name,
651061da546Spatrick                                       lldb::SBCommandPluginInterface *impl,
652061da546Spatrick                                       const char *help) {
653*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, impl, help);
654*f6aab3d8Srobert   return AddCommand(name, impl, help, /*syntax=*/nullptr,
655*f6aab3d8Srobert                     /*auto_repeat_command=*/"");
656061da546Spatrick }
657061da546Spatrick 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax)658061da546Spatrick lldb::SBCommand SBCommand::AddCommand(const char *name,
659061da546Spatrick                                       lldb::SBCommandPluginInterface *impl,
660061da546Spatrick                                       const char *help, const char *syntax) {
661*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax);
662*f6aab3d8Srobert   return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/"");
663dda28197Spatrick }
664dda28197Spatrick 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax,const char * auto_repeat_command)665dda28197Spatrick lldb::SBCommand SBCommand::AddCommand(const char *name,
666dda28197Spatrick                                       lldb::SBCommandPluginInterface *impl,
667dda28197Spatrick                                       const char *help, const char *syntax,
668dda28197Spatrick                                       const char *auto_repeat_command) {
669*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command);
670061da546Spatrick 
671061da546Spatrick   if (!IsValid())
672*f6aab3d8Srobert     return lldb::SBCommand();
673061da546Spatrick   if (!m_opaque_sp->IsMultiwordObject())
674*f6aab3d8Srobert     return lldb::SBCommand();
675061da546Spatrick   lldb::CommandObjectSP new_command_sp;
676061da546Spatrick   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
677dda28197Spatrick       m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax,
678dda28197Spatrick       /*flags=*/0, auto_repeat_command);
679061da546Spatrick   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
680*f6aab3d8Srobert     return lldb::SBCommand(new_command_sp);
681*f6aab3d8Srobert   return lldb::SBCommand();
682061da546Spatrick }
683061da546Spatrick 
GetFlags()684061da546Spatrick uint32_t SBCommand::GetFlags() {
685*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this);
686061da546Spatrick 
687061da546Spatrick   return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);
688061da546Spatrick }
689061da546Spatrick 
SetFlags(uint32_t flags)690061da546Spatrick void SBCommand::SetFlags(uint32_t flags) {
691*f6aab3d8Srobert   LLDB_INSTRUMENT_VA(this, flags);
692061da546Spatrick 
693061da546Spatrick   if (IsValid())
694061da546Spatrick     m_opaque_sp->GetFlags().Set(flags);
695061da546Spatrick }
696