brintos

brintos / llvm-project-archived public Read only

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