1 //===-- SBCommandInterpreter.cpp ------------------------------------------===//
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 #include "lldb/lldb-types.h"
10 
11 #include "lldb/Interpreter/CommandInterpreter.h"
12 #include "lldb/Interpreter/CommandObjectMultiword.h"
13 #include "lldb/Interpreter/CommandReturnObject.h"
14 #include "lldb/Target/Target.h"
15 #include "lldb/Utility/Instrumentation.h"
16 #include "lldb/Utility/Listener.h"
17 
18 #include "lldb/API/SBBroadcaster.h"
19 #include "lldb/API/SBCommandInterpreter.h"
20 #include "lldb/API/SBCommandInterpreterRunOptions.h"
21 #include "lldb/API/SBCommandReturnObject.h"
22 #include "lldb/API/SBEvent.h"
23 #include "lldb/API/SBExecutionContext.h"
24 #include "lldb/API/SBListener.h"
25 #include "lldb/API/SBProcess.h"
26 #include "lldb/API/SBStream.h"
27 #include "lldb/API/SBStringList.h"
28 #include "lldb/API/SBTarget.h"
29 
30 #include <memory>
31 #include <optional>
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 namespace lldb_private {
37 class CommandPluginInterfaceImplementation : public CommandObjectParsed {
38 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="")39   CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,
40                                        const char *name,
41                                        lldb::SBCommandPluginInterface *backend,
42                                        const char *help = nullptr,
43                                        const char *syntax = nullptr,
44                                        uint32_t flags = 0,
45                                        const char *auto_repeat_command = "")
46       : CommandObjectParsed(interpreter, name, help, syntax, flags),
47         m_backend(backend) {
48     m_auto_repeat_command =
49         auto_repeat_command == nullptr
50             ? std::nullopt
51             : std::optional<std::string>(auto_repeat_command);
52     // We don't know whether any given command coming from this interface takes
53     // arguments or not so here we're just disabling the basic args check.
54     CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar};
55     m_arguments.push_back({none_arg});
56   }
57 
IsRemovable() const58   bool IsRemovable() const override { return true; }
59 
60   /// More documentation is available in lldb::CommandObject::GetRepeatCommand,
61   /// but in short, if std::nullopt is returned, the previous command will be
62   /// repeated, and if an empty string is returned, no commands will be
63   /// executed.
GetRepeatCommand(Args & current_command_args,uint32_t index)64   std::optional<std::string> GetRepeatCommand(Args &current_command_args,
65                                               uint32_t index) override {
66     if (!m_auto_repeat_command)
67       return std::nullopt;
68     else
69       return m_auto_repeat_command;
70   }
71 
72 protected:
DoExecute(Args & command,CommandReturnObject & result)73   void DoExecute(Args &command, CommandReturnObject &result) override {
74     SBCommandReturnObject sb_return(result);
75     SBCommandInterpreter sb_interpreter(&m_interpreter);
76     SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
77     m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), sb_return);
78   }
79   std::shared_ptr<lldb::SBCommandPluginInterface> m_backend;
80   std::optional<std::string> m_auto_repeat_command;
81 };
82 } // namespace lldb_private
83 
SBCommandInterpreter()84 SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() {
85   LLDB_INSTRUMENT_VA(this);
86 }
87 
SBCommandInterpreter(CommandInterpreter * interpreter)88 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)
89     : m_opaque_ptr(interpreter) {
90   LLDB_INSTRUMENT_VA(this, interpreter);
91 }
92 
SBCommandInterpreter(const SBCommandInterpreter & rhs)93 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs)
94     : m_opaque_ptr(rhs.m_opaque_ptr) {
95   LLDB_INSTRUMENT_VA(this, rhs);
96 }
97 
98 SBCommandInterpreter::~SBCommandInterpreter() = default;
99 
100 const SBCommandInterpreter &SBCommandInterpreter::
operator =(const SBCommandInterpreter & rhs)101 operator=(const SBCommandInterpreter &rhs) {
102   LLDB_INSTRUMENT_VA(this, rhs);
103 
104   m_opaque_ptr = rhs.m_opaque_ptr;
105   return *this;
106 }
107 
IsValid() const108 bool SBCommandInterpreter::IsValid() const {
109   LLDB_INSTRUMENT_VA(this);
110   return this->operator bool();
111 }
operator bool() const112 SBCommandInterpreter::operator bool() const {
113   LLDB_INSTRUMENT_VA(this);
114 
115   return m_opaque_ptr != nullptr;
116 }
117 
CommandExists(const char * cmd)118 bool SBCommandInterpreter::CommandExists(const char *cmd) {
119   LLDB_INSTRUMENT_VA(this, cmd);
120 
121   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd)
122                                           : false);
123 }
124 
UserCommandExists(const char * cmd)125 bool SBCommandInterpreter::UserCommandExists(const char *cmd) {
126   LLDB_INSTRUMENT_VA(this, cmd);
127 
128   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->UserCommandExists(cmd)
129                                           : false);
130 }
131 
AliasExists(const char * cmd)132 bool SBCommandInterpreter::AliasExists(const char *cmd) {
133   LLDB_INSTRUMENT_VA(this, cmd);
134 
135   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd)
136                                           : false);
137 }
138 
IsActive()139 bool SBCommandInterpreter::IsActive() {
140   LLDB_INSTRUMENT_VA(this);
141 
142   return (IsValid() ? m_opaque_ptr->IsActive() : false);
143 }
144 
WasInterrupted() const145 bool SBCommandInterpreter::WasInterrupted() const {
146   LLDB_INSTRUMENT_VA(this);
147 
148   return (IsValid() ? m_opaque_ptr->GetDebugger().InterruptRequested() : false);
149 }
150 
InterruptCommand()151 bool SBCommandInterpreter::InterruptCommand() {
152   LLDB_INSTRUMENT_VA(this);
153 
154   return (IsValid() ? m_opaque_ptr->InterruptCommand() : false);
155 }
156 
GetIOHandlerControlSequence(char ch)157 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) {
158   LLDB_INSTRUMENT_VA(this, ch);
159 
160   if (!IsValid())
161     return nullptr;
162 
163   return ConstString(
164              m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch))
165       .GetCString();
166 }
167 
168 lldb::ReturnStatus
HandleCommand(const char * command_line,SBCommandReturnObject & result,bool add_to_history)169 SBCommandInterpreter::HandleCommand(const char *command_line,
170                                     SBCommandReturnObject &result,
171                                     bool add_to_history) {
172   LLDB_INSTRUMENT_VA(this, command_line, result, add_to_history);
173 
174   SBExecutionContext sb_exe_ctx;
175   return HandleCommand(command_line, sb_exe_ctx, result, add_to_history);
176 }
177 
HandleCommand(const char * command_line,SBExecutionContext & override_context,SBCommandReturnObject & result,bool add_to_history)178 lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
179     const char *command_line, SBExecutionContext &override_context,
180     SBCommandReturnObject &result, bool add_to_history) {
181   LLDB_INSTRUMENT_VA(this, command_line, override_context, result,
182                      add_to_history);
183 
184   result.Clear();
185   if (command_line && IsValid()) {
186     result.ref().SetInteractive(false);
187     auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo;
188     if (override_context.get())
189       m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
190                                   override_context.get()->Lock(true),
191                                   result.ref());
192     else
193       m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
194                                   result.ref());
195   } else {
196     result->AppendError(
197         "SBCommandInterpreter or the command line is not valid");
198   }
199 
200   return result.GetStatus();
201 }
202 
HandleCommandsFromFile(lldb::SBFileSpec & file,lldb::SBExecutionContext & override_context,lldb::SBCommandInterpreterRunOptions & options,lldb::SBCommandReturnObject result)203 void SBCommandInterpreter::HandleCommandsFromFile(
204     lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context,
205     lldb::SBCommandInterpreterRunOptions &options,
206     lldb::SBCommandReturnObject result) {
207   LLDB_INSTRUMENT_VA(this, file, override_context, options, result);
208 
209   if (!IsValid()) {
210     result->AppendError("SBCommandInterpreter is not valid.");
211     return;
212   }
213 
214   if (!file.IsValid()) {
215     SBStream s;
216     file.GetDescription(s);
217     result->AppendErrorWithFormat("File is not valid: %s.", s.GetData());
218   }
219 
220   FileSpec tmp_spec = file.ref();
221   if (override_context.get())
222     m_opaque_ptr->HandleCommandsFromFile(tmp_spec,
223                                          override_context.get()->Lock(true),
224                                          options.ref(),
225                                          result.ref());
226 
227   else
228     m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref());
229 }
230 
HandleCompletion(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,SBStringList & matches)231 int SBCommandInterpreter::HandleCompletion(
232     const char *current_line, const char *cursor, const char *last_char,
233     int match_start_point, int max_return_elements, SBStringList &matches) {
234   LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point,
235                      max_return_elements, matches);
236 
237   SBStringList dummy_descriptions;
238   return HandleCompletionWithDescriptions(
239       current_line, cursor, last_char, match_start_point, max_return_elements,
240       matches, dummy_descriptions);
241 }
242 
HandleCompletionWithDescriptions(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,SBStringList & matches,SBStringList & descriptions)243 int SBCommandInterpreter::HandleCompletionWithDescriptions(
244     const char *current_line, const char *cursor, const char *last_char,
245     int match_start_point, int max_return_elements, SBStringList &matches,
246     SBStringList &descriptions) {
247   LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point,
248                      max_return_elements, matches, descriptions);
249 
250   // Sanity check the arguments that are passed in: cursor & last_char have to
251   // be within the current_line.
252   if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
253     return 0;
254 
255   if (cursor < current_line || last_char < current_line)
256     return 0;
257 
258   size_t current_line_size = strlen(current_line);
259   if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||
260       last_char - current_line > static_cast<ptrdiff_t>(current_line_size))
261     return 0;
262 
263   if (!IsValid())
264     return 0;
265 
266   lldb_private::StringList lldb_matches, lldb_descriptions;
267   CompletionResult result;
268   CompletionRequest request(current_line, cursor - current_line, result);
269   m_opaque_ptr->HandleCompletion(request);
270   result.GetMatches(lldb_matches);
271   result.GetDescriptions(lldb_descriptions);
272 
273   // Make the result array indexed from 1 again by adding the 'common prefix'
274   // of all completions as element 0. This is done to emulate the old API.
275   if (request.GetParsedLine().GetArgumentCount() == 0) {
276     // If we got an empty string, insert nothing.
277     lldb_matches.InsertStringAtIndex(0, "");
278     lldb_descriptions.InsertStringAtIndex(0, "");
279   } else {
280     // Now figure out if there is a common substring, and if so put that in
281     // element 0, otherwise put an empty string in element 0.
282     std::string command_partial_str = request.GetCursorArgumentPrefix().str();
283 
284     std::string common_prefix = lldb_matches.LongestCommonPrefix();
285     const size_t partial_name_len = command_partial_str.size();
286     common_prefix.erase(0, partial_name_len);
287 
288     // If we matched a unique single command, add a space... Only do this if
289     // the completer told us this was a complete word, however...
290     if (lldb_matches.GetSize() == 1) {
291       char quote_char = request.GetParsedArg().GetQuoteChar();
292       common_prefix =
293           Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
294       if (request.GetParsedArg().IsQuoted())
295         common_prefix.push_back(quote_char);
296       common_prefix.push_back(' ');
297     }
298     lldb_matches.InsertStringAtIndex(0, common_prefix.c_str());
299     lldb_descriptions.InsertStringAtIndex(0, "");
300   }
301 
302   SBStringList temp_matches_list(&lldb_matches);
303   matches.AppendList(temp_matches_list);
304   SBStringList temp_descriptions_list(&lldb_descriptions);
305   descriptions.AppendList(temp_descriptions_list);
306   return result.GetNumberOfResults();
307 }
308 
HandleCompletionWithDescriptions(const char * current_line,uint32_t cursor_pos,int match_start_point,int max_return_elements,SBStringList & matches,SBStringList & descriptions)309 int SBCommandInterpreter::HandleCompletionWithDescriptions(
310     const char *current_line, uint32_t cursor_pos, int match_start_point,
311     int max_return_elements, SBStringList &matches,
312     SBStringList &descriptions) {
313   LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point,
314                      max_return_elements, matches, descriptions);
315 
316   const char *cursor = current_line + cursor_pos;
317   const char *last_char = current_line + strlen(current_line);
318   return HandleCompletionWithDescriptions(
319       current_line, cursor, last_char, match_start_point, max_return_elements,
320       matches, descriptions);
321 }
322 
HandleCompletion(const char * current_line,uint32_t cursor_pos,int match_start_point,int max_return_elements,lldb::SBStringList & matches)323 int SBCommandInterpreter::HandleCompletion(const char *current_line,
324                                            uint32_t cursor_pos,
325                                            int match_start_point,
326                                            int max_return_elements,
327                                            lldb::SBStringList &matches) {
328   LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point,
329                      max_return_elements, matches);
330 
331   const char *cursor = current_line + cursor_pos;
332   const char *last_char = current_line + strlen(current_line);
333   return HandleCompletion(current_line, cursor, last_char, match_start_point,
334                           max_return_elements, matches);
335 }
336 
HasCommands()337 bool SBCommandInterpreter::HasCommands() {
338   LLDB_INSTRUMENT_VA(this);
339 
340   return (IsValid() ? m_opaque_ptr->HasCommands() : false);
341 }
342 
HasAliases()343 bool SBCommandInterpreter::HasAliases() {
344   LLDB_INSTRUMENT_VA(this);
345 
346   return (IsValid() ? m_opaque_ptr->HasAliases() : false);
347 }
348 
HasAliasOptions()349 bool SBCommandInterpreter::HasAliasOptions() {
350   LLDB_INSTRUMENT_VA(this);
351 
352   return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);
353 }
354 
IsInteractive()355 bool SBCommandInterpreter::IsInteractive() {
356   LLDB_INSTRUMENT_VA(this);
357 
358   return (IsValid() ? m_opaque_ptr->IsInteractive() : false);
359 }
360 
GetProcess()361 SBProcess SBCommandInterpreter::GetProcess() {
362   LLDB_INSTRUMENT_VA(this);
363 
364   SBProcess sb_process;
365   ProcessSP process_sp;
366   if (IsValid()) {
367     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
368     if (target_sp) {
369       std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
370       process_sp = target_sp->GetProcessSP();
371       sb_process.SetSP(process_sp);
372     }
373   }
374 
375   return sb_process;
376 }
377 
GetDebugger()378 SBDebugger SBCommandInterpreter::GetDebugger() {
379   LLDB_INSTRUMENT_VA(this);
380 
381   SBDebugger sb_debugger;
382   if (IsValid())
383     sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
384 
385   return sb_debugger;
386 }
387 
GetPromptOnQuit()388 bool SBCommandInterpreter::GetPromptOnQuit() {
389   LLDB_INSTRUMENT_VA(this);
390 
391   return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);
392 }
393 
SetPromptOnQuit(bool b)394 void SBCommandInterpreter::SetPromptOnQuit(bool b) {
395   LLDB_INSTRUMENT_VA(this, b);
396 
397   if (IsValid())
398     m_opaque_ptr->SetPromptOnQuit(b);
399 }
400 
AllowExitCodeOnQuit(bool allow)401 void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
402   LLDB_INSTRUMENT_VA(this, allow);
403 
404   if (m_opaque_ptr)
405     m_opaque_ptr->AllowExitCodeOnQuit(allow);
406 }
407 
HasCustomQuitExitCode()408 bool SBCommandInterpreter::HasCustomQuitExitCode() {
409   LLDB_INSTRUMENT_VA(this);
410 
411   bool exited = false;
412   if (m_opaque_ptr)
413     m_opaque_ptr->GetQuitExitCode(exited);
414   return exited;
415 }
416 
GetQuitStatus()417 int SBCommandInterpreter::GetQuitStatus() {
418   LLDB_INSTRUMENT_VA(this);
419 
420   bool exited = false;
421   return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
422 }
423 
ResolveCommand(const char * command_line,SBCommandReturnObject & result)424 void SBCommandInterpreter::ResolveCommand(const char *command_line,
425                                           SBCommandReturnObject &result) {
426   LLDB_INSTRUMENT_VA(this, command_line, result);
427 
428   result.Clear();
429   if (command_line && IsValid()) {
430     m_opaque_ptr->ResolveCommand(command_line, result.ref());
431   } else {
432     result->AppendError(
433         "SBCommandInterpreter or the command line is not valid");
434   }
435 }
436 
get()437 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; }
438 
ref()439 CommandInterpreter &SBCommandInterpreter::ref() {
440   assert(m_opaque_ptr);
441   return *m_opaque_ptr;
442 }
443 
reset(lldb_private::CommandInterpreter * interpreter)444 void SBCommandInterpreter::reset(
445     lldb_private::CommandInterpreter *interpreter) {
446   m_opaque_ptr = interpreter;
447 }
448 
SourceInitFileInGlobalDirectory(SBCommandReturnObject & result)449 void SBCommandInterpreter::SourceInitFileInGlobalDirectory(
450     SBCommandReturnObject &result) {
451   LLDB_INSTRUMENT_VA(this, result);
452 
453   result.Clear();
454   if (IsValid()) {
455     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
456     std::unique_lock<std::recursive_mutex> lock;
457     if (target_sp)
458       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
459     m_opaque_ptr->SourceInitFileGlobal(result.ref());
460   } else {
461     result->AppendError("SBCommandInterpreter is not valid");
462   }
463 }
464 
SourceInitFileInHomeDirectory(SBCommandReturnObject & result)465 void SBCommandInterpreter::SourceInitFileInHomeDirectory(
466     SBCommandReturnObject &result) {
467   LLDB_INSTRUMENT_VA(this, result);
468 
469   SourceInitFileInHomeDirectory(result, /*is_repl=*/false);
470 }
471 
SourceInitFileInHomeDirectory(SBCommandReturnObject & result,bool is_repl)472 void SBCommandInterpreter::SourceInitFileInHomeDirectory(
473     SBCommandReturnObject &result, bool is_repl) {
474   LLDB_INSTRUMENT_VA(this, result, is_repl);
475 
476   result.Clear();
477   if (IsValid()) {
478     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
479     std::unique_lock<std::recursive_mutex> lock;
480     if (target_sp)
481       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
482     m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl);
483   } else {
484     result->AppendError("SBCommandInterpreter is not valid");
485   }
486 }
487 
SourceInitFileInCurrentWorkingDirectory(SBCommandReturnObject & result)488 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
489     SBCommandReturnObject &result) {
490   LLDB_INSTRUMENT_VA(this, result);
491 
492   result.Clear();
493   if (IsValid()) {
494     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
495     std::unique_lock<std::recursive_mutex> lock;
496     if (target_sp)
497       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
498     m_opaque_ptr->SourceInitFileCwd(result.ref());
499   } else {
500     result->AppendError("SBCommandInterpreter is not valid");
501   }
502 }
503 
GetBroadcaster()504 SBBroadcaster SBCommandInterpreter::GetBroadcaster() {
505   LLDB_INSTRUMENT_VA(this);
506 
507   SBBroadcaster broadcaster(m_opaque_ptr, false);
508 
509   return broadcaster;
510 }
511 
GetBroadcasterClass()512 const char *SBCommandInterpreter::GetBroadcasterClass() {
513   LLDB_INSTRUMENT();
514 
515   return CommandInterpreter::GetStaticBroadcasterClass().AsCString();
516 }
517 
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type)518 const char *SBCommandInterpreter::GetArgumentTypeAsCString(
519     const lldb::CommandArgumentType arg_type) {
520   LLDB_INSTRUMENT_VA(arg_type);
521 
522   return ConstString(CommandObject::GetArgumentTypeAsCString(arg_type))
523       .GetCString();
524 }
525 
GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type)526 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString(
527     const lldb::CommandArgumentType arg_type) {
528   LLDB_INSTRUMENT_VA(arg_type);
529 
530   return ConstString(CommandObject::GetArgumentDescriptionAsCString(arg_type))
531       .GetCString();
532 }
533 
EventIsCommandInterpreterEvent(const lldb::SBEvent & event)534 bool SBCommandInterpreter::EventIsCommandInterpreterEvent(
535     const lldb::SBEvent &event) {
536   LLDB_INSTRUMENT_VA(event);
537 
538   return event.GetBroadcasterClass() ==
539          SBCommandInterpreter::GetBroadcasterClass();
540 }
541 
SetCommandOverrideCallback(const char * command_name,lldb::CommandOverrideCallback callback,void * baton)542 bool SBCommandInterpreter::SetCommandOverrideCallback(
543     const char *command_name, lldb::CommandOverrideCallback callback,
544     void *baton) {
545   LLDB_INSTRUMENT_VA(this, command_name, callback, baton);
546 
547   if (command_name && command_name[0] && IsValid()) {
548     llvm::StringRef command_name_str = command_name;
549     CommandObject *cmd_obj =
550         m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
551     if (cmd_obj) {
552       assert(command_name_str.empty());
553       cmd_obj->SetOverrideCallback(callback, baton);
554       return true;
555     }
556   }
557   return false;
558 }
559 
AddMultiwordCommand(const char * name,const char * help)560 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name,
561                                                           const char *help) {
562   LLDB_INSTRUMENT_VA(this, name, help);
563 
564   lldb::CommandObjectSP new_command_sp(
565       new CommandObjectMultiword(*m_opaque_ptr, name, help));
566   new_command_sp->GetAsMultiwordCommand()->SetRemovable(true);
567   Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);
568   if (add_error.Success())
569     return lldb::SBCommand(new_command_sp);
570   return lldb::SBCommand();
571 }
572 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help)573 lldb::SBCommand SBCommandInterpreter::AddCommand(
574     const char *name, lldb::SBCommandPluginInterface *impl, const char *help) {
575   LLDB_INSTRUMENT_VA(this, name, impl, help);
576 
577   return AddCommand(name, impl, help, /*syntax=*/nullptr,
578                     /*auto_repeat_command=*/"");
579 }
580 
581 lldb::SBCommand
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax)582 SBCommandInterpreter::AddCommand(const char *name,
583                                  lldb::SBCommandPluginInterface *impl,
584                                  const char *help, const char *syntax) {
585   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax);
586   return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/"");
587 }
588 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax,const char * auto_repeat_command)589 lldb::SBCommand SBCommandInterpreter::AddCommand(
590     const char *name, lldb::SBCommandPluginInterface *impl, const char *help,
591     const char *syntax, const char *auto_repeat_command) {
592   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command);
593 
594   lldb::CommandObjectSP new_command_sp;
595   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
596       *m_opaque_ptr, name, impl, help, syntax, /*flags=*/0,
597       auto_repeat_command);
598 
599   Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);
600   if (add_error.Success())
601     return lldb::SBCommand(new_command_sp);
602   return lldb::SBCommand();
603 }
604 
SBCommand()605 SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); }
606 
SBCommand(lldb::CommandObjectSP cmd_sp)607 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {}
608 
IsValid()609 bool SBCommand::IsValid() {
610   LLDB_INSTRUMENT_VA(this);
611   return this->operator bool();
612 }
operator bool() const613 SBCommand::operator bool() const {
614   LLDB_INSTRUMENT_VA(this);
615 
616   return m_opaque_sp.get() != nullptr;
617 }
618 
GetName()619 const char *SBCommand::GetName() {
620   LLDB_INSTRUMENT_VA(this);
621 
622   return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr);
623 }
624 
GetHelp()625 const char *SBCommand::GetHelp() {
626   LLDB_INSTRUMENT_VA(this);
627 
628   return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString()
629                     : nullptr);
630 }
631 
GetHelpLong()632 const char *SBCommand::GetHelpLong() {
633   LLDB_INSTRUMENT_VA(this);
634 
635   return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString()
636                     : nullptr);
637 }
638 
SetHelp(const char * help)639 void SBCommand::SetHelp(const char *help) {
640   LLDB_INSTRUMENT_VA(this, help);
641 
642   if (IsValid())
643     m_opaque_sp->SetHelp(help);
644 }
645 
SetHelpLong(const char * help)646 void SBCommand::SetHelpLong(const char *help) {
647   LLDB_INSTRUMENT_VA(this, help);
648 
649   if (IsValid())
650     m_opaque_sp->SetHelpLong(help);
651 }
652 
AddMultiwordCommand(const char * name,const char * help)653 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name,
654                                                const char *help) {
655   LLDB_INSTRUMENT_VA(this, name, help);
656 
657   if (!IsValid())
658     return lldb::SBCommand();
659   if (!m_opaque_sp->IsMultiwordObject())
660     return lldb::SBCommand();
661   CommandObjectMultiword *new_command = new CommandObjectMultiword(
662       m_opaque_sp->GetCommandInterpreter(), name, help);
663   new_command->SetRemovable(true);
664   lldb::CommandObjectSP new_command_sp(new_command);
665   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
666     return lldb::SBCommand(new_command_sp);
667   return lldb::SBCommand();
668 }
669 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help)670 lldb::SBCommand SBCommand::AddCommand(const char *name,
671                                       lldb::SBCommandPluginInterface *impl,
672                                       const char *help) {
673   LLDB_INSTRUMENT_VA(this, name, impl, help);
674   return AddCommand(name, impl, help, /*syntax=*/nullptr,
675                     /*auto_repeat_command=*/"");
676 }
677 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax)678 lldb::SBCommand SBCommand::AddCommand(const char *name,
679                                       lldb::SBCommandPluginInterface *impl,
680                                       const char *help, const char *syntax) {
681   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax);
682   return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/"");
683 }
684 
AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax,const char * auto_repeat_command)685 lldb::SBCommand SBCommand::AddCommand(const char *name,
686                                       lldb::SBCommandPluginInterface *impl,
687                                       const char *help, const char *syntax,
688                                       const char *auto_repeat_command) {
689   LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command);
690 
691   if (!IsValid())
692     return lldb::SBCommand();
693   if (!m_opaque_sp->IsMultiwordObject())
694     return lldb::SBCommand();
695   lldb::CommandObjectSP new_command_sp;
696   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
697       m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax,
698       /*flags=*/0, auto_repeat_command);
699   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
700     return lldb::SBCommand(new_command_sp);
701   return lldb::SBCommand();
702 }
703 
GetFlags()704 uint32_t SBCommand::GetFlags() {
705   LLDB_INSTRUMENT_VA(this);
706 
707   return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);
708 }
709 
SetFlags(uint32_t flags)710 void SBCommand::SetFlags(uint32_t flags) {
711   LLDB_INSTRUMENT_VA(this, flags);
712 
713   if (IsValid())
714     m_opaque_sp->GetFlags().Set(flags);
715 }
716