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 "SBReproducerPrivate.h"
12 #include "lldb/Interpreter/CommandInterpreter.h"
13 #include "lldb/Interpreter/CommandObjectMultiword.h"
14 #include "lldb/Interpreter/CommandReturnObject.h"
15 #include "lldb/Target/Target.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 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 class CommandPluginInterfaceImplementation : public CommandObjectParsed {
36 public:
37   CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,
38                                        const char *name,
39                                        lldb::SBCommandPluginInterface *backend,
40                                        const char *help = nullptr,
41                                        const char *syntax = nullptr,
42                                        uint32_t flags = 0,
43                                        const char *auto_repeat_command = "")
44       : CommandObjectParsed(interpreter, name, help, syntax, flags),
45         m_backend(backend) {
46     m_auto_repeat_command =
47         auto_repeat_command == nullptr
48             ? llvm::None
49             : llvm::Optional<std::string>(auto_repeat_command);
50   }
51 
52   bool IsRemovable() const override { return true; }
53 
54   /// More documentation is available in lldb::CommandObject::GetRepeatCommand,
55   /// but in short, if nullptr is returned, the previous command will be
56   /// repeated, and if an empty string is returned, no commands will be
57   /// executed.
58   const char *GetRepeatCommand(Args &current_command_args,
59                                uint32_t index) override {
60     if (!m_auto_repeat_command)
61       return nullptr;
62     else
63       return m_auto_repeat_command->c_str();
64   }
65 
66 protected:
67   bool DoExecute(Args &command, CommandReturnObject &result) override {
68     SBCommandReturnObject sb_return(result);
69     SBCommandInterpreter sb_interpreter(&m_interpreter);
70     SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
71     bool ret = m_backend->DoExecute(
72         debugger_sb, command.GetArgumentVector(), sb_return);
73     return ret;
74   }
75   std::shared_ptr<lldb::SBCommandPluginInterface> m_backend;
76   llvm::Optional<std::string> m_auto_repeat_command;
77 };
78 
79 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)
80     : m_opaque_ptr(interpreter) {
81   LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreter,
82                           (lldb_private::CommandInterpreter *), interpreter);
83 
84 }
85 
86 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs)
87     : m_opaque_ptr(rhs.m_opaque_ptr) {
88   LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreter,
89                           (const lldb::SBCommandInterpreter &), rhs);
90 }
91 
92 SBCommandInterpreter::~SBCommandInterpreter() = default;
93 
94 const SBCommandInterpreter &SBCommandInterpreter::
95 operator=(const SBCommandInterpreter &rhs) {
96   LLDB_RECORD_METHOD(
97       const lldb::SBCommandInterpreter &,
98       SBCommandInterpreter, operator=,(const lldb::SBCommandInterpreter &),
99       rhs);
100 
101   m_opaque_ptr = rhs.m_opaque_ptr;
102   return LLDB_RECORD_RESULT(*this);
103 }
104 
105 bool SBCommandInterpreter::IsValid() const {
106   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, IsValid);
107   return this->operator bool();
108 }
109 SBCommandInterpreter::operator bool() const {
110   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, operator bool);
111 
112   return m_opaque_ptr != nullptr;
113 }
114 
115 bool SBCommandInterpreter::CommandExists(const char *cmd) {
116   LLDB_RECORD_METHOD(bool, SBCommandInterpreter, CommandExists, (const char *),
117                      cmd);
118 
119   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd)
120                                           : false);
121 }
122 
123 bool SBCommandInterpreter::AliasExists(const char *cmd) {
124   LLDB_RECORD_METHOD(bool, SBCommandInterpreter, AliasExists, (const char *),
125                      cmd);
126 
127   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd)
128                                           : false);
129 }
130 
131 bool SBCommandInterpreter::IsActive() {
132   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, IsActive);
133 
134   return (IsValid() ? m_opaque_ptr->IsActive() : false);
135 }
136 
137 bool SBCommandInterpreter::WasInterrupted() const {
138   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, WasInterrupted);
139 
140   return (IsValid() ? m_opaque_ptr->WasInterrupted() : false);
141 }
142 
143 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) {
144   LLDB_RECORD_METHOD(const char *, SBCommandInterpreter,
145                      GetIOHandlerControlSequence, (char), ch);
146 
147   return (IsValid()
148               ? m_opaque_ptr->GetDebugger()
149                     .GetTopIOHandlerControlSequence(ch)
150                     .GetCString()
151               : nullptr);
152 }
153 
154 lldb::ReturnStatus
155 SBCommandInterpreter::HandleCommand(const char *command_line,
156                                     SBCommandReturnObject &result,
157                                     bool add_to_history) {
158   LLDB_RECORD_METHOD(lldb::ReturnStatus, SBCommandInterpreter, HandleCommand,
159                      (const char *, lldb::SBCommandReturnObject &, bool),
160                      command_line, result, add_to_history);
161 
162   SBExecutionContext sb_exe_ctx;
163   return HandleCommand(command_line, sb_exe_ctx, result, add_to_history);
164 }
165 
166 lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
167     const char *command_line, SBExecutionContext &override_context,
168     SBCommandReturnObject &result, bool add_to_history) {
169   LLDB_RECORD_METHOD(lldb::ReturnStatus, SBCommandInterpreter, HandleCommand,
170                      (const char *, lldb::SBExecutionContext &,
171                       lldb::SBCommandReturnObject &, bool),
172                      command_line, override_context, result, add_to_history);
173 
174 
175   ExecutionContext ctx, *ctx_ptr;
176   if (override_context.get()) {
177     ctx = override_context.get()->Lock(true);
178     ctx_ptr = &ctx;
179   } else
180     ctx_ptr = nullptr;
181 
182   result.Clear();
183   if (command_line && IsValid()) {
184     result.ref().SetInteractive(false);
185     m_opaque_ptr->HandleCommand(command_line,
186                                 add_to_history ? eLazyBoolYes : eLazyBoolNo,
187                                 result.ref(), ctx_ptr);
188   } else {
189     result->AppendError(
190         "SBCommandInterpreter or the command line is not valid");
191     result->SetStatus(eReturnStatusFailed);
192   }
193 
194 
195   return result.GetStatus();
196 }
197 
198 void SBCommandInterpreter::HandleCommandsFromFile(
199     lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context,
200     lldb::SBCommandInterpreterRunOptions &options,
201     lldb::SBCommandReturnObject result) {
202   LLDB_RECORD_METHOD(void, SBCommandInterpreter, HandleCommandsFromFile,
203                      (lldb::SBFileSpec &, lldb::SBExecutionContext &,
204                       lldb::SBCommandInterpreterRunOptions &,
205                       lldb::SBCommandReturnObject),
206                      file, override_context, options, result);
207 
208   if (!IsValid()) {
209     result->AppendError("SBCommandInterpreter is not valid.");
210     result->SetStatus(eReturnStatusFailed);
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     result->SetStatus(eReturnStatusFailed);
219   }
220 
221   FileSpec tmp_spec = file.ref();
222   ExecutionContext ctx, *ctx_ptr;
223   if (override_context.get()) {
224     ctx = override_context.get()->Lock(true);
225     ctx_ptr = &ctx;
226   } else
227     ctx_ptr = nullptr;
228 
229   m_opaque_ptr->HandleCommandsFromFile(tmp_spec, ctx_ptr, options.ref(),
230                                        result.ref());
231 }
232 
233 int SBCommandInterpreter::HandleCompletion(
234     const char *current_line, const char *cursor, const char *last_char,
235     int match_start_point, int max_return_elements, SBStringList &matches) {
236   LLDB_RECORD_METHOD(int, SBCommandInterpreter, HandleCompletion,
237                      (const char *, const char *, const char *, int, int,
238                       lldb::SBStringList &),
239                      current_line, cursor, last_char, match_start_point,
240                      max_return_elements, matches);
241 
242   SBStringList dummy_descriptions;
243   return HandleCompletionWithDescriptions(
244       current_line, cursor, last_char, match_start_point, max_return_elements,
245       matches, dummy_descriptions);
246 }
247 
248 int SBCommandInterpreter::HandleCompletionWithDescriptions(
249     const char *current_line, const char *cursor, const char *last_char,
250     int match_start_point, int max_return_elements, SBStringList &matches,
251     SBStringList &descriptions) {
252   LLDB_RECORD_METHOD(int, SBCommandInterpreter,
253                      HandleCompletionWithDescriptions,
254                      (const char *, const char *, const char *, int, int,
255                       lldb::SBStringList &, lldb::SBStringList &),
256                      current_line, cursor, last_char, match_start_point,
257                      max_return_elements, matches, descriptions);
258 
259   // Sanity check the arguments that are passed in: cursor & last_char have to
260   // be within the current_line.
261   if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
262     return 0;
263 
264   if (cursor < current_line || last_char < current_line)
265     return 0;
266 
267   size_t current_line_size = strlen(current_line);
268   if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||
269       last_char - current_line > static_cast<ptrdiff_t>(current_line_size))
270     return 0;
271 
272   if (!IsValid())
273     return 0;
274 
275   lldb_private::StringList lldb_matches, lldb_descriptions;
276   CompletionResult result;
277   CompletionRequest request(current_line, cursor - current_line, result);
278   m_opaque_ptr->HandleCompletion(request);
279   result.GetMatches(lldb_matches);
280   result.GetDescriptions(lldb_descriptions);
281 
282   // Make the result array indexed from 1 again by adding the 'common prefix'
283   // of all completions as element 0. This is done to emulate the old API.
284   if (request.GetParsedLine().GetArgumentCount() == 0) {
285     // If we got an empty string, insert nothing.
286     lldb_matches.InsertStringAtIndex(0, "");
287     lldb_descriptions.InsertStringAtIndex(0, "");
288   } else {
289     // Now figure out if there is a common substring, and if so put that in
290     // element 0, otherwise put an empty string in element 0.
291     std::string command_partial_str = request.GetCursorArgumentPrefix().str();
292 
293     std::string common_prefix = lldb_matches.LongestCommonPrefix();
294     const size_t partial_name_len = command_partial_str.size();
295     common_prefix.erase(0, partial_name_len);
296 
297     // If we matched a unique single command, add a space... Only do this if
298     // the completer told us this was a complete word, however...
299     if (lldb_matches.GetSize() == 1) {
300       char quote_char = request.GetParsedArg().GetQuoteChar();
301       common_prefix =
302           Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
303       if (request.GetParsedArg().IsQuoted())
304         common_prefix.push_back(quote_char);
305       common_prefix.push_back(' ');
306     }
307     lldb_matches.InsertStringAtIndex(0, common_prefix.c_str());
308     lldb_descriptions.InsertStringAtIndex(0, "");
309   }
310 
311   SBStringList temp_matches_list(&lldb_matches);
312   matches.AppendList(temp_matches_list);
313   SBStringList temp_descriptions_list(&lldb_descriptions);
314   descriptions.AppendList(temp_descriptions_list);
315   return result.GetNumberOfResults();
316 }
317 
318 int SBCommandInterpreter::HandleCompletionWithDescriptions(
319     const char *current_line, uint32_t cursor_pos, int match_start_point,
320     int max_return_elements, SBStringList &matches,
321     SBStringList &descriptions) {
322   LLDB_RECORD_METHOD(int, SBCommandInterpreter,
323                      HandleCompletionWithDescriptions,
324                      (const char *, uint32_t, int, int, lldb::SBStringList &,
325                       lldb::SBStringList &),
326                      current_line, cursor_pos, match_start_point,
327                      max_return_elements, matches, descriptions);
328 
329   const char *cursor = current_line + cursor_pos;
330   const char *last_char = current_line + strlen(current_line);
331   return HandleCompletionWithDescriptions(
332       current_line, cursor, last_char, match_start_point, max_return_elements,
333       matches, descriptions);
334 }
335 
336 int SBCommandInterpreter::HandleCompletion(const char *current_line,
337                                            uint32_t cursor_pos,
338                                            int match_start_point,
339                                            int max_return_elements,
340                                            lldb::SBStringList &matches) {
341   LLDB_RECORD_METHOD(int, SBCommandInterpreter, HandleCompletion,
342                      (const char *, uint32_t, int, int, lldb::SBStringList &),
343                      current_line, cursor_pos, match_start_point,
344                      max_return_elements, matches);
345 
346   const char *cursor = current_line + cursor_pos;
347   const char *last_char = current_line + strlen(current_line);
348   return HandleCompletion(current_line, cursor, last_char, match_start_point,
349                           max_return_elements, matches);
350 }
351 
352 bool SBCommandInterpreter::HasCommands() {
353   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasCommands);
354 
355   return (IsValid() ? m_opaque_ptr->HasCommands() : false);
356 }
357 
358 bool SBCommandInterpreter::HasAliases() {
359   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasAliases);
360 
361   return (IsValid() ? m_opaque_ptr->HasAliases() : false);
362 }
363 
364 bool SBCommandInterpreter::HasAliasOptions() {
365   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasAliasOptions);
366 
367   return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);
368 }
369 
370 SBProcess SBCommandInterpreter::GetProcess() {
371   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBProcess, SBCommandInterpreter, GetProcess);
372 
373   SBProcess sb_process;
374   ProcessSP process_sp;
375   if (IsValid()) {
376     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
377     if (target_sp) {
378       std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
379       process_sp = target_sp->GetProcessSP();
380       sb_process.SetSP(process_sp);
381     }
382   }
383 
384   return LLDB_RECORD_RESULT(sb_process);
385 }
386 
387 SBDebugger SBCommandInterpreter::GetDebugger() {
388   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBDebugger, SBCommandInterpreter,
389                              GetDebugger);
390 
391   SBDebugger sb_debugger;
392   if (IsValid())
393     sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
394 
395   return LLDB_RECORD_RESULT(sb_debugger);
396 }
397 
398 bool SBCommandInterpreter::GetPromptOnQuit() {
399   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, GetPromptOnQuit);
400 
401   return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);
402 }
403 
404 void SBCommandInterpreter::SetPromptOnQuit(bool b) {
405   LLDB_RECORD_METHOD(void, SBCommandInterpreter, SetPromptOnQuit, (bool), b);
406 
407   if (IsValid())
408     m_opaque_ptr->SetPromptOnQuit(b);
409 }
410 
411 void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
412   LLDB_RECORD_METHOD(void, SBCommandInterpreter, AllowExitCodeOnQuit, (bool),
413                      allow);
414 
415   if (m_opaque_ptr)
416     m_opaque_ptr->AllowExitCodeOnQuit(allow);
417 }
418 
419 bool SBCommandInterpreter::HasCustomQuitExitCode() {
420   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasCustomQuitExitCode);
421 
422   bool exited = false;
423   if (m_opaque_ptr)
424     m_opaque_ptr->GetQuitExitCode(exited);
425   return exited;
426 }
427 
428 int SBCommandInterpreter::GetQuitStatus() {
429   LLDB_RECORD_METHOD_NO_ARGS(int, SBCommandInterpreter, GetQuitStatus);
430 
431   bool exited = false;
432   return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
433 }
434 
435 void SBCommandInterpreter::ResolveCommand(const char *command_line,
436                                           SBCommandReturnObject &result) {
437   LLDB_RECORD_METHOD(void, SBCommandInterpreter, ResolveCommand,
438                      (const char *, lldb::SBCommandReturnObject &),
439                      command_line, result);
440 
441   result.Clear();
442   if (command_line && IsValid()) {
443     m_opaque_ptr->ResolveCommand(command_line, result.ref());
444   } else {
445     result->AppendError(
446         "SBCommandInterpreter or the command line is not valid");
447     result->SetStatus(eReturnStatusFailed);
448   }
449 }
450 
451 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; }
452 
453 CommandInterpreter &SBCommandInterpreter::ref() {
454   assert(m_opaque_ptr);
455   return *m_opaque_ptr;
456 }
457 
458 void SBCommandInterpreter::reset(
459     lldb_private::CommandInterpreter *interpreter) {
460   m_opaque_ptr = interpreter;
461 }
462 
463 void SBCommandInterpreter::SourceInitFileInHomeDirectory(
464     SBCommandReturnObject &result) {
465   LLDB_RECORD_METHOD(void, SBCommandInterpreter, SourceInitFileInHomeDirectory,
466                      (lldb::SBCommandReturnObject &), result);
467 
468   result.Clear();
469   if (IsValid()) {
470     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
471     std::unique_lock<std::recursive_mutex> lock;
472     if (target_sp)
473       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
474     m_opaque_ptr->SourceInitFileHome(result.ref());
475   } else {
476     result->AppendError("SBCommandInterpreter is not valid");
477     result->SetStatus(eReturnStatusFailed);
478   }
479 }
480 
481 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
482     SBCommandReturnObject &result) {
483   LLDB_RECORD_METHOD(void, SBCommandInterpreter,
484                      SourceInitFileInCurrentWorkingDirectory,
485                      (lldb::SBCommandReturnObject &), result);
486 
487   result.Clear();
488   if (IsValid()) {
489     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
490     std::unique_lock<std::recursive_mutex> lock;
491     if (target_sp)
492       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
493     m_opaque_ptr->SourceInitFileCwd(result.ref());
494   } else {
495     result->AppendError("SBCommandInterpreter is not valid");
496     result->SetStatus(eReturnStatusFailed);
497   }
498 }
499 
500 SBBroadcaster SBCommandInterpreter::GetBroadcaster() {
501   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBCommandInterpreter,
502                              GetBroadcaster);
503 
504 
505   SBBroadcaster broadcaster(m_opaque_ptr, false);
506 
507 
508   return LLDB_RECORD_RESULT(broadcaster);
509 }
510 
511 const char *SBCommandInterpreter::GetBroadcasterClass() {
512   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBCommandInterpreter,
513                                     GetBroadcasterClass);
514 
515   return CommandInterpreter::GetStaticBroadcasterClass().AsCString();
516 }
517 
518 const char *SBCommandInterpreter::GetArgumentTypeAsCString(
519     const lldb::CommandArgumentType arg_type) {
520   LLDB_RECORD_STATIC_METHOD(const char *, SBCommandInterpreter,
521                             GetArgumentTypeAsCString,
522                             (const lldb::CommandArgumentType), arg_type);
523 
524   return CommandObject::GetArgumentTypeAsCString(arg_type);
525 }
526 
527 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString(
528     const lldb::CommandArgumentType arg_type) {
529   LLDB_RECORD_STATIC_METHOD(const char *, SBCommandInterpreter,
530                             GetArgumentDescriptionAsCString,
531                             (const lldb::CommandArgumentType), arg_type);
532 
533   return CommandObject::GetArgumentDescriptionAsCString(arg_type);
534 }
535 
536 bool SBCommandInterpreter::EventIsCommandInterpreterEvent(
537     const lldb::SBEvent &event) {
538   LLDB_RECORD_STATIC_METHOD(bool, SBCommandInterpreter,
539                             EventIsCommandInterpreterEvent,
540                             (const lldb::SBEvent &), event);
541 
542   return event.GetBroadcasterClass() ==
543          SBCommandInterpreter::GetBroadcasterClass();
544 }
545 
546 bool SBCommandInterpreter::SetCommandOverrideCallback(
547     const char *command_name, lldb::CommandOverrideCallback callback,
548     void *baton) {
549   LLDB_RECORD_DUMMY(bool, SBCommandInterpreter, SetCommandOverrideCallback,
550                     (const char *, lldb::CommandOverrideCallback, void *),
551                     command_name, callback, baton);
552 
553   if (command_name && command_name[0] && IsValid()) {
554     llvm::StringRef command_name_str = command_name;
555     CommandObject *cmd_obj =
556         m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
557     if (cmd_obj) {
558       assert(command_name_str.empty());
559       cmd_obj->SetOverrideCallback(callback, baton);
560       return true;
561     }
562   }
563   return false;
564 }
565 
566 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name,
567                                                           const char *help) {
568   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddMultiwordCommand,
569                      (const char *, const char *), name, help);
570 
571   CommandObjectMultiword *new_command =
572       new CommandObjectMultiword(*m_opaque_ptr, name, help);
573   new_command->SetRemovable(true);
574   lldb::CommandObjectSP new_command_sp(new_command);
575   if (new_command_sp &&
576       m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
577     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
578   return LLDB_RECORD_RESULT(lldb::SBCommand());
579 }
580 
581 lldb::SBCommand SBCommandInterpreter::AddCommand(
582     const char *name, lldb::SBCommandPluginInterface *impl, const char *help) {
583   LLDB_RECORD_METHOD(
584       lldb::SBCommand, SBCommandInterpreter, AddCommand,
585       (const char *, lldb::SBCommandPluginInterface *, const char *), name,
586       impl, help);
587 
588   return LLDB_RECORD_RESULT(AddCommand(name, impl, help, /*syntax=*/nullptr,
589                                        /*auto_repeat_command=*/""))
590 }
591 
592 lldb::SBCommand
593 SBCommandInterpreter::AddCommand(const char *name,
594                                  lldb::SBCommandPluginInterface *impl,
595                                  const char *help, const char *syntax) {
596   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
597                      (const char *, lldb::SBCommandPluginInterface *,
598                       const char *, const char *),
599                      name, impl, help, syntax);
600   return LLDB_RECORD_RESULT(
601       AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""))
602 }
603 
604 lldb::SBCommand SBCommandInterpreter::AddCommand(
605     const char *name, lldb::SBCommandPluginInterface *impl, const char *help,
606     const char *syntax, const char *auto_repeat_command) {
607   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
608                      (const char *, lldb::SBCommandPluginInterface *,
609                       const char *, const char *, const char *),
610                      name, impl, help, syntax, auto_repeat_command);
611 
612   lldb::CommandObjectSP new_command_sp;
613   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
614       *m_opaque_ptr, name, impl, help, syntax, /*flags=*/0,
615       auto_repeat_command);
616 
617   if (new_command_sp &&
618       m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
619     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
620   return LLDB_RECORD_RESULT(lldb::SBCommand());
621 }
622 
623 SBCommand::SBCommand() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommand); }
624 
625 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {}
626 
627 bool SBCommand::IsValid() {
628   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommand, IsValid);
629   return this->operator bool();
630 }
631 SBCommand::operator bool() const {
632   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommand, operator bool);
633 
634   return m_opaque_sp.get() != nullptr;
635 }
636 
637 const char *SBCommand::GetName() {
638   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetName);
639 
640   return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr);
641 }
642 
643 const char *SBCommand::GetHelp() {
644   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetHelp);
645 
646   return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString()
647                     : nullptr);
648 }
649 
650 const char *SBCommand::GetHelpLong() {
651   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetHelpLong);
652 
653   return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString()
654                     : nullptr);
655 }
656 
657 void SBCommand::SetHelp(const char *help) {
658   LLDB_RECORD_METHOD(void, SBCommand, SetHelp, (const char *), help);
659 
660   if (IsValid())
661     m_opaque_sp->SetHelp(help);
662 }
663 
664 void SBCommand::SetHelpLong(const char *help) {
665   LLDB_RECORD_METHOD(void, SBCommand, SetHelpLong, (const char *), help);
666 
667   if (IsValid())
668     m_opaque_sp->SetHelpLong(help);
669 }
670 
671 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name,
672                                                const char *help) {
673   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddMultiwordCommand,
674                      (const char *, const char *), name, help);
675 
676   if (!IsValid())
677     return LLDB_RECORD_RESULT(lldb::SBCommand());
678   if (!m_opaque_sp->IsMultiwordObject())
679     return LLDB_RECORD_RESULT(lldb::SBCommand());
680   CommandObjectMultiword *new_command = new CommandObjectMultiword(
681       m_opaque_sp->GetCommandInterpreter(), name, help);
682   new_command->SetRemovable(true);
683   lldb::CommandObjectSP new_command_sp(new_command);
684   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
685     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
686   return LLDB_RECORD_RESULT(lldb::SBCommand());
687 }
688 
689 lldb::SBCommand SBCommand::AddCommand(const char *name,
690                                       lldb::SBCommandPluginInterface *impl,
691                                       const char *help) {
692   LLDB_RECORD_METHOD(
693       lldb::SBCommand, SBCommand, AddCommand,
694       (const char *, lldb::SBCommandPluginInterface *, const char *), name,
695       impl, help);
696   return LLDB_RECORD_RESULT(AddCommand(name, impl, help, /*syntax=*/nullptr,
697                                        /*auto_repeat_command=*/""))
698 }
699 
700 lldb::SBCommand SBCommand::AddCommand(const char *name,
701                                       lldb::SBCommandPluginInterface *impl,
702                                       const char *help, const char *syntax) {
703   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddCommand,
704                      (const char *, lldb::SBCommandPluginInterface *,
705                       const char *, const char *),
706                      name, impl, help, syntax);
707   return LLDB_RECORD_RESULT(
708       AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""))
709 }
710 
711 lldb::SBCommand SBCommand::AddCommand(const char *name,
712                                       lldb::SBCommandPluginInterface *impl,
713                                       const char *help, const char *syntax,
714                                       const char *auto_repeat_command) {
715   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddCommand,
716                      (const char *, lldb::SBCommandPluginInterface *,
717                       const char *, const char *, const char *),
718                      name, impl, help, syntax, auto_repeat_command);
719 
720   if (!IsValid())
721     return LLDB_RECORD_RESULT(lldb::SBCommand());
722   if (!m_opaque_sp->IsMultiwordObject())
723     return LLDB_RECORD_RESULT(lldb::SBCommand());
724   lldb::CommandObjectSP new_command_sp;
725   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
726       m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax,
727       /*flags=*/0, auto_repeat_command);
728   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
729     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
730   return LLDB_RECORD_RESULT(lldb::SBCommand());
731 }
732 
733 uint32_t SBCommand::GetFlags() {
734   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBCommand, GetFlags);
735 
736   return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);
737 }
738 
739 void SBCommand::SetFlags(uint32_t flags) {
740   LLDB_RECORD_METHOD(void, SBCommand, SetFlags, (uint32_t), flags);
741 
742   if (IsValid())
743     m_opaque_sp->GetFlags().Set(flags);
744 }
745 
746 namespace lldb_private {
747 namespace repro {
748 
749 template <> void RegisterMethods<SBCommandInterpreter>(Registry &R) {
750   LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreter,
751                             (lldb_private::CommandInterpreter *));
752   LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreter,
753                             (const lldb::SBCommandInterpreter &));
754   LLDB_REGISTER_METHOD(
755       const lldb::SBCommandInterpreter &,
756       SBCommandInterpreter, operator=,(const lldb::SBCommandInterpreter &));
757   LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, IsValid, ());
758   LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, operator bool, ());
759   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, CommandExists,
760                        (const char *));
761   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, AliasExists,
762                        (const char *));
763   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, IsActive, ());
764   LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, WasInterrupted, ());
765   LLDB_REGISTER_METHOD(const char *, SBCommandInterpreter,
766                        GetIOHandlerControlSequence, (char));
767   LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandInterpreter,
768                        HandleCommand,
769                        (const char *, lldb::SBCommandReturnObject &, bool));
770   LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandInterpreter,
771                        HandleCommand,
772                        (const char *, lldb::SBExecutionContext &,
773                         lldb::SBCommandReturnObject &, bool));
774   LLDB_REGISTER_METHOD(void, SBCommandInterpreter, HandleCommandsFromFile,
775                        (lldb::SBFileSpec &, lldb::SBExecutionContext &,
776                         lldb::SBCommandInterpreterRunOptions &,
777                         lldb::SBCommandReturnObject));
778   LLDB_REGISTER_METHOD(int, SBCommandInterpreter, HandleCompletion,
779                        (const char *, const char *, const char *, int, int,
780                         lldb::SBStringList &));
781   LLDB_REGISTER_METHOD(int, SBCommandInterpreter,
782                        HandleCompletionWithDescriptions,
783                        (const char *, const char *, const char *, int, int,
784                         lldb::SBStringList &, lldb::SBStringList &));
785   LLDB_REGISTER_METHOD(int, SBCommandInterpreter,
786                        HandleCompletionWithDescriptions,
787                        (const char *, uint32_t, int, int,
788                         lldb::SBStringList &, lldb::SBStringList &));
789   LLDB_REGISTER_METHOD(
790       int, SBCommandInterpreter, HandleCompletion,
791       (const char *, uint32_t, int, int, lldb::SBStringList &));
792   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasCommands, ());
793   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasAliases, ());
794   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasAliasOptions, ());
795   LLDB_REGISTER_METHOD(lldb::SBProcess, SBCommandInterpreter, GetProcess, ());
796   LLDB_REGISTER_METHOD(lldb::SBDebugger, SBCommandInterpreter, GetDebugger,
797                        ());
798   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, GetPromptOnQuit, ());
799   LLDB_REGISTER_METHOD(void, SBCommandInterpreter, SetPromptOnQuit, (bool));
800   LLDB_REGISTER_METHOD(void, SBCommandInterpreter, AllowExitCodeOnQuit,
801                        (bool));
802   LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasCustomQuitExitCode, ());
803   LLDB_REGISTER_METHOD(int, SBCommandInterpreter, GetQuitStatus, ());
804   LLDB_REGISTER_METHOD(void, SBCommandInterpreter, ResolveCommand,
805                        (const char *, lldb::SBCommandReturnObject &));
806   LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
807                        SourceInitFileInHomeDirectory,
808                        (lldb::SBCommandReturnObject &));
809   LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
810                        SourceInitFileInCurrentWorkingDirectory,
811                        (lldb::SBCommandReturnObject &));
812   LLDB_REGISTER_METHOD(lldb::SBBroadcaster, SBCommandInterpreter,
813                        GetBroadcaster, ());
814   LLDB_REGISTER_STATIC_METHOD(const char *, SBCommandInterpreter,
815                               GetBroadcasterClass, ());
816   LLDB_REGISTER_STATIC_METHOD(const char *, SBCommandInterpreter,
817                               GetArgumentTypeAsCString,
818                               (const lldb::CommandArgumentType));
819   LLDB_REGISTER_STATIC_METHOD(const char *, SBCommandInterpreter,
820                               GetArgumentDescriptionAsCString,
821                               (const lldb::CommandArgumentType));
822   LLDB_REGISTER_STATIC_METHOD(bool, SBCommandInterpreter,
823                               EventIsCommandInterpreterEvent,
824                               (const lldb::SBEvent &));
825   LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommandInterpreter,
826                        AddMultiwordCommand, (const char *, const char *));
827   LLDB_REGISTER_METHOD(
828       lldb::SBCommand, SBCommandInterpreter, AddCommand,
829       (const char *, lldb::SBCommandPluginInterface *, const char *));
830   LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
831                        (const char *, lldb::SBCommandPluginInterface *,
832                         const char *, const char *));
833   LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
834                        (const char *, lldb::SBCommandPluginInterface *,
835                         const char *, const char *, const char *));
836   LLDB_REGISTER_CONSTRUCTOR(SBCommand, ());
837   LLDB_REGISTER_METHOD(bool, SBCommand, IsValid, ());
838   LLDB_REGISTER_METHOD_CONST(bool, SBCommand, operator bool, ());
839   LLDB_REGISTER_METHOD(const char *, SBCommand, GetName, ());
840   LLDB_REGISTER_METHOD(const char *, SBCommand, GetHelp, ());
841   LLDB_REGISTER_METHOD(const char *, SBCommand, GetHelpLong, ());
842   LLDB_REGISTER_METHOD(void, SBCommand, SetHelp, (const char *));
843   LLDB_REGISTER_METHOD(void, SBCommand, SetHelpLong, (const char *));
844   LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommand, AddMultiwordCommand,
845                        (const char *, const char *));
846   LLDB_REGISTER_METHOD(
847       lldb::SBCommand, SBCommand, AddCommand,
848       (const char *, lldb::SBCommandPluginInterface *, const char *));
849   LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommand, AddCommand,
850                        (const char *, lldb::SBCommandPluginInterface *,
851                         const char *, const char *));
852   LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommand, AddCommand,
853                        (const char *, lldb::SBCommandPluginInterface *,
854                         const char *, const char *, const char *));
855   LLDB_REGISTER_METHOD(uint32_t, SBCommand, GetFlags, ());
856   LLDB_REGISTER_METHOD(void, SBCommand, SetFlags, (uint32_t));
857 }
858 }
859 }
860