Path: blob/main/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp
39587 views
//===-- SBCommandInterpreter.cpp ------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Utility/StructuredData.h"9#include "lldb/lldb-types.h"1011#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"1718#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"2930#include <memory>31#include <optional>3233using namespace lldb;34using namespace lldb_private;3536namespace lldb_private {37class CommandPluginInterfaceImplementation : public CommandObjectParsed {38public:39CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,40const char *name,41lldb::SBCommandPluginInterface *backend,42const char *help = nullptr,43const char *syntax = nullptr,44uint32_t flags = 0,45const char *auto_repeat_command = "")46: CommandObjectParsed(interpreter, name, help, syntax, flags),47m_backend(backend) {48m_auto_repeat_command =49auto_repeat_command == nullptr50? std::nullopt51: std::optional<std::string>(auto_repeat_command);52// We don't know whether any given command coming from this interface takes53// arguments or not so here we're just disabling the basic args check.54CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar};55m_arguments.push_back({none_arg});56}5758bool IsRemovable() const override { return true; }5960/// More documentation is available in lldb::CommandObject::GetRepeatCommand,61/// but in short, if std::nullopt is returned, the previous command will be62/// repeated, and if an empty string is returned, no commands will be63/// executed.64std::optional<std::string> GetRepeatCommand(Args ¤t_command_args,65uint32_t index) override {66if (!m_auto_repeat_command)67return std::nullopt;68else69return m_auto_repeat_command;70}7172protected:73void DoExecute(Args &command, CommandReturnObject &result) override {74SBCommandReturnObject sb_return(result);75SBCommandInterpreter sb_interpreter(&m_interpreter);76SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());77m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), sb_return);78}79std::shared_ptr<lldb::SBCommandPluginInterface> m_backend;80std::optional<std::string> m_auto_repeat_command;81};82} // namespace lldb_private8384SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() {85LLDB_INSTRUMENT_VA(this);86}8788SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)89: m_opaque_ptr(interpreter) {90LLDB_INSTRUMENT_VA(this, interpreter);91}9293SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs)94: m_opaque_ptr(rhs.m_opaque_ptr) {95LLDB_INSTRUMENT_VA(this, rhs);96}9798SBCommandInterpreter::~SBCommandInterpreter() = default;99100const SBCommandInterpreter &SBCommandInterpreter::101operator=(const SBCommandInterpreter &rhs) {102LLDB_INSTRUMENT_VA(this, rhs);103104m_opaque_ptr = rhs.m_opaque_ptr;105return *this;106}107108bool SBCommandInterpreter::IsValid() const {109LLDB_INSTRUMENT_VA(this);110return this->operator bool();111}112SBCommandInterpreter::operator bool() const {113LLDB_INSTRUMENT_VA(this);114115return m_opaque_ptr != nullptr;116}117118bool SBCommandInterpreter::CommandExists(const char *cmd) {119LLDB_INSTRUMENT_VA(this, cmd);120121return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd)122: false);123}124125bool SBCommandInterpreter::UserCommandExists(const char *cmd) {126LLDB_INSTRUMENT_VA(this, cmd);127128return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->UserCommandExists(cmd)129: false);130}131132bool SBCommandInterpreter::AliasExists(const char *cmd) {133LLDB_INSTRUMENT_VA(this, cmd);134135return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd)136: false);137}138139bool SBCommandInterpreter::IsActive() {140LLDB_INSTRUMENT_VA(this);141142return (IsValid() ? m_opaque_ptr->IsActive() : false);143}144145bool SBCommandInterpreter::WasInterrupted() const {146LLDB_INSTRUMENT_VA(this);147148return (IsValid() ? m_opaque_ptr->GetDebugger().InterruptRequested() : false);149}150151bool SBCommandInterpreter::InterruptCommand() {152LLDB_INSTRUMENT_VA(this);153154return (IsValid() ? m_opaque_ptr->InterruptCommand() : false);155}156157const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) {158LLDB_INSTRUMENT_VA(this, ch);159160if (!IsValid())161return nullptr;162163return ConstString(164m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch))165.GetCString();166}167168lldb::ReturnStatus169SBCommandInterpreter::HandleCommand(const char *command_line,170SBCommandReturnObject &result,171bool add_to_history) {172LLDB_INSTRUMENT_VA(this, command_line, result, add_to_history);173174SBExecutionContext sb_exe_ctx;175return HandleCommand(command_line, sb_exe_ctx, result, add_to_history);176}177178lldb::ReturnStatus SBCommandInterpreter::HandleCommand(179const char *command_line, SBExecutionContext &override_context,180SBCommandReturnObject &result, bool add_to_history) {181LLDB_INSTRUMENT_VA(this, command_line, override_context, result,182add_to_history);183184result.Clear();185if (command_line && IsValid()) {186result.ref().SetInteractive(false);187auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo;188if (override_context.get())189m_opaque_ptr->HandleCommand(command_line, do_add_to_history,190override_context.get()->Lock(true),191result.ref());192else193m_opaque_ptr->HandleCommand(command_line, do_add_to_history,194result.ref());195} else {196result->AppendError(197"SBCommandInterpreter or the command line is not valid");198}199200return result.GetStatus();201}202203void SBCommandInterpreter::HandleCommandsFromFile(204lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context,205lldb::SBCommandInterpreterRunOptions &options,206lldb::SBCommandReturnObject result) {207LLDB_INSTRUMENT_VA(this, file, override_context, options, result);208209if (!IsValid()) {210result->AppendError("SBCommandInterpreter is not valid.");211return;212}213214if (!file.IsValid()) {215SBStream s;216file.GetDescription(s);217result->AppendErrorWithFormat("File is not valid: %s.", s.GetData());218}219220FileSpec tmp_spec = file.ref();221if (override_context.get())222m_opaque_ptr->HandleCommandsFromFile(tmp_spec,223override_context.get()->Lock(true),224options.ref(),225result.ref());226227else228m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref());229}230231int SBCommandInterpreter::HandleCompletion(232const char *current_line, const char *cursor, const char *last_char,233int match_start_point, int max_return_elements, SBStringList &matches) {234LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point,235max_return_elements, matches);236237SBStringList dummy_descriptions;238return HandleCompletionWithDescriptions(239current_line, cursor, last_char, match_start_point, max_return_elements,240matches, dummy_descriptions);241}242243int SBCommandInterpreter::HandleCompletionWithDescriptions(244const char *current_line, const char *cursor, const char *last_char,245int match_start_point, int max_return_elements, SBStringList &matches,246SBStringList &descriptions) {247LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point,248max_return_elements, matches, descriptions);249250// Sanity check the arguments that are passed in: cursor & last_char have to251// be within the current_line.252if (current_line == nullptr || cursor == nullptr || last_char == nullptr)253return 0;254255if (cursor < current_line || last_char < current_line)256return 0;257258size_t current_line_size = strlen(current_line);259if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||260last_char - current_line > static_cast<ptrdiff_t>(current_line_size))261return 0;262263if (!IsValid())264return 0;265266lldb_private::StringList lldb_matches, lldb_descriptions;267CompletionResult result;268CompletionRequest request(current_line, cursor - current_line, result);269m_opaque_ptr->HandleCompletion(request);270result.GetMatches(lldb_matches);271result.GetDescriptions(lldb_descriptions);272273// 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.275if (request.GetParsedLine().GetArgumentCount() == 0) {276// If we got an empty string, insert nothing.277lldb_matches.InsertStringAtIndex(0, "");278lldb_descriptions.InsertStringAtIndex(0, "");279} else {280// Now figure out if there is a common substring, and if so put that in281// element 0, otherwise put an empty string in element 0.282std::string command_partial_str = request.GetCursorArgumentPrefix().str();283284std::string common_prefix = lldb_matches.LongestCommonPrefix();285const size_t partial_name_len = command_partial_str.size();286common_prefix.erase(0, partial_name_len);287288// If we matched a unique single command, add a space... Only do this if289// the completer told us this was a complete word, however...290if (lldb_matches.GetSize() == 1) {291char quote_char = request.GetParsedArg().GetQuoteChar();292common_prefix =293Args::EscapeLLDBCommandArgument(common_prefix, quote_char);294if (request.GetParsedArg().IsQuoted())295common_prefix.push_back(quote_char);296common_prefix.push_back(' ');297}298lldb_matches.InsertStringAtIndex(0, common_prefix.c_str());299lldb_descriptions.InsertStringAtIndex(0, "");300}301302SBStringList temp_matches_list(&lldb_matches);303matches.AppendList(temp_matches_list);304SBStringList temp_descriptions_list(&lldb_descriptions);305descriptions.AppendList(temp_descriptions_list);306return result.GetNumberOfResults();307}308309int SBCommandInterpreter::HandleCompletionWithDescriptions(310const char *current_line, uint32_t cursor_pos, int match_start_point,311int max_return_elements, SBStringList &matches,312SBStringList &descriptions) {313LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point,314max_return_elements, matches, descriptions);315316const char *cursor = current_line + cursor_pos;317const char *last_char = current_line + strlen(current_line);318return HandleCompletionWithDescriptions(319current_line, cursor, last_char, match_start_point, max_return_elements,320matches, descriptions);321}322323int SBCommandInterpreter::HandleCompletion(const char *current_line,324uint32_t cursor_pos,325int match_start_point,326int max_return_elements,327lldb::SBStringList &matches) {328LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point,329max_return_elements, matches);330331const char *cursor = current_line + cursor_pos;332const char *last_char = current_line + strlen(current_line);333return HandleCompletion(current_line, cursor, last_char, match_start_point,334max_return_elements, matches);335}336337bool SBCommandInterpreter::HasCommands() {338LLDB_INSTRUMENT_VA(this);339340return (IsValid() ? m_opaque_ptr->HasCommands() : false);341}342343bool SBCommandInterpreter::HasAliases() {344LLDB_INSTRUMENT_VA(this);345346return (IsValid() ? m_opaque_ptr->HasAliases() : false);347}348349bool SBCommandInterpreter::HasAliasOptions() {350LLDB_INSTRUMENT_VA(this);351352return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);353}354355bool SBCommandInterpreter::IsInteractive() {356LLDB_INSTRUMENT_VA(this);357358return (IsValid() ? m_opaque_ptr->IsInteractive() : false);359}360361SBProcess SBCommandInterpreter::GetProcess() {362LLDB_INSTRUMENT_VA(this);363364SBProcess sb_process;365ProcessSP process_sp;366if (IsValid()) {367TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());368if (target_sp) {369std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());370process_sp = target_sp->GetProcessSP();371sb_process.SetSP(process_sp);372}373}374375return sb_process;376}377378SBDebugger SBCommandInterpreter::GetDebugger() {379LLDB_INSTRUMENT_VA(this);380381SBDebugger sb_debugger;382if (IsValid())383sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());384385return sb_debugger;386}387388bool SBCommandInterpreter::GetPromptOnQuit() {389LLDB_INSTRUMENT_VA(this);390391return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);392}393394void SBCommandInterpreter::SetPromptOnQuit(bool b) {395LLDB_INSTRUMENT_VA(this, b);396397if (IsValid())398m_opaque_ptr->SetPromptOnQuit(b);399}400401void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {402LLDB_INSTRUMENT_VA(this, allow);403404if (m_opaque_ptr)405m_opaque_ptr->AllowExitCodeOnQuit(allow);406}407408bool SBCommandInterpreter::HasCustomQuitExitCode() {409LLDB_INSTRUMENT_VA(this);410411bool exited = false;412if (m_opaque_ptr)413m_opaque_ptr->GetQuitExitCode(exited);414return exited;415}416417int SBCommandInterpreter::GetQuitStatus() {418LLDB_INSTRUMENT_VA(this);419420bool exited = false;421return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);422}423424void SBCommandInterpreter::ResolveCommand(const char *command_line,425SBCommandReturnObject &result) {426LLDB_INSTRUMENT_VA(this, command_line, result);427428result.Clear();429if (command_line && IsValid()) {430m_opaque_ptr->ResolveCommand(command_line, result.ref());431} else {432result->AppendError(433"SBCommandInterpreter or the command line is not valid");434}435}436437CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; }438439CommandInterpreter &SBCommandInterpreter::ref() {440assert(m_opaque_ptr);441return *m_opaque_ptr;442}443444void SBCommandInterpreter::reset(445lldb_private::CommandInterpreter *interpreter) {446m_opaque_ptr = interpreter;447}448449void SBCommandInterpreter::SourceInitFileInGlobalDirectory(450SBCommandReturnObject &result) {451LLDB_INSTRUMENT_VA(this, result);452453result.Clear();454if (IsValid()) {455TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());456std::unique_lock<std::recursive_mutex> lock;457if (target_sp)458lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());459m_opaque_ptr->SourceInitFileGlobal(result.ref());460} else {461result->AppendError("SBCommandInterpreter is not valid");462}463}464465void SBCommandInterpreter::SourceInitFileInHomeDirectory(466SBCommandReturnObject &result) {467LLDB_INSTRUMENT_VA(this, result);468469SourceInitFileInHomeDirectory(result, /*is_repl=*/false);470}471472void SBCommandInterpreter::SourceInitFileInHomeDirectory(473SBCommandReturnObject &result, bool is_repl) {474LLDB_INSTRUMENT_VA(this, result, is_repl);475476result.Clear();477if (IsValid()) {478TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());479std::unique_lock<std::recursive_mutex> lock;480if (target_sp)481lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());482m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl);483} else {484result->AppendError("SBCommandInterpreter is not valid");485}486}487488void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(489SBCommandReturnObject &result) {490LLDB_INSTRUMENT_VA(this, result);491492result.Clear();493if (IsValid()) {494TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());495std::unique_lock<std::recursive_mutex> lock;496if (target_sp)497lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());498m_opaque_ptr->SourceInitFileCwd(result.ref());499} else {500result->AppendError("SBCommandInterpreter is not valid");501}502}503504SBBroadcaster SBCommandInterpreter::GetBroadcaster() {505LLDB_INSTRUMENT_VA(this);506507SBBroadcaster broadcaster(m_opaque_ptr, false);508509return broadcaster;510}511512const char *SBCommandInterpreter::GetBroadcasterClass() {513LLDB_INSTRUMENT();514515return ConstString(CommandInterpreter::GetStaticBroadcasterClass())516.AsCString();517}518519const char *SBCommandInterpreter::GetArgumentTypeAsCString(520const lldb::CommandArgumentType arg_type) {521LLDB_INSTRUMENT_VA(arg_type);522523return ConstString(CommandObject::GetArgumentTypeAsCString(arg_type))524.GetCString();525}526527const char *SBCommandInterpreter::GetArgumentDescriptionAsCString(528const lldb::CommandArgumentType arg_type) {529LLDB_INSTRUMENT_VA(arg_type);530531return ConstString(CommandObject::GetArgumentDescriptionAsCString(arg_type))532.GetCString();533}534535bool SBCommandInterpreter::EventIsCommandInterpreterEvent(536const lldb::SBEvent &event) {537LLDB_INSTRUMENT_VA(event);538539return event.GetBroadcasterClass() ==540SBCommandInterpreter::GetBroadcasterClass();541}542543bool SBCommandInterpreter::SetCommandOverrideCallback(544const char *command_name, lldb::CommandOverrideCallback callback,545void *baton) {546LLDB_INSTRUMENT_VA(this, command_name, callback, baton);547548if (command_name && command_name[0] && IsValid()) {549llvm::StringRef command_name_str = command_name;550CommandObject *cmd_obj =551m_opaque_ptr->GetCommandObjectForCommand(command_name_str);552if (cmd_obj) {553assert(command_name_str.empty());554cmd_obj->SetOverrideCallback(callback, baton);555return true;556}557}558return false;559}560561SBStructuredData SBCommandInterpreter::GetStatistics() {562LLDB_INSTRUMENT_VA(this);563564SBStructuredData data;565if (!IsValid())566return data;567568std::string json_str =569llvm::formatv("{0:2}", m_opaque_ptr->GetStatistics()).str();570data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str));571return data;572}573574SBStructuredData SBCommandInterpreter::GetTranscript() {575LLDB_INSTRUMENT_VA(this);576577SBStructuredData data;578if (IsValid())579// A deep copy is performed by `std::make_shared` on the580// `StructuredData::Array`, via its implicitly-declared copy constructor.581// This ensures thread-safety between the user changing the returned582// `SBStructuredData` and the `CommandInterpreter` changing its internal583// `m_transcript`.584data.m_impl_up->SetObjectSP(585std::make_shared<StructuredData::Array>(m_opaque_ptr->GetTranscript()));586return data;587}588589lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name,590const char *help) {591LLDB_INSTRUMENT_VA(this, name, help);592593lldb::CommandObjectSP new_command_sp(594new CommandObjectMultiword(*m_opaque_ptr, name, help));595new_command_sp->GetAsMultiwordCommand()->SetRemovable(true);596Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);597if (add_error.Success())598return lldb::SBCommand(new_command_sp);599return lldb::SBCommand();600}601602lldb::SBCommand SBCommandInterpreter::AddCommand(603const char *name, lldb::SBCommandPluginInterface *impl, const char *help) {604LLDB_INSTRUMENT_VA(this, name, impl, help);605606return AddCommand(name, impl, help, /*syntax=*/nullptr,607/*auto_repeat_command=*/"");608}609610lldb::SBCommand611SBCommandInterpreter::AddCommand(const char *name,612lldb::SBCommandPluginInterface *impl,613const char *help, const char *syntax) {614LLDB_INSTRUMENT_VA(this, name, impl, help, syntax);615return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/"");616}617618lldb::SBCommand SBCommandInterpreter::AddCommand(619const char *name, lldb::SBCommandPluginInterface *impl, const char *help,620const char *syntax, const char *auto_repeat_command) {621LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command);622623lldb::CommandObjectSP new_command_sp;624new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(625*m_opaque_ptr, name, impl, help, syntax, /*flags=*/0,626auto_repeat_command);627628Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);629if (add_error.Success())630return lldb::SBCommand(new_command_sp);631return lldb::SBCommand();632}633634SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); }635636SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {}637638bool SBCommand::IsValid() {639LLDB_INSTRUMENT_VA(this);640return this->operator bool();641}642SBCommand::operator bool() const {643LLDB_INSTRUMENT_VA(this);644645return m_opaque_sp.get() != nullptr;646}647648const char *SBCommand::GetName() {649LLDB_INSTRUMENT_VA(this);650651return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr);652}653654const char *SBCommand::GetHelp() {655LLDB_INSTRUMENT_VA(this);656657return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString()658: nullptr);659}660661const char *SBCommand::GetHelpLong() {662LLDB_INSTRUMENT_VA(this);663664return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString()665: nullptr);666}667668void SBCommand::SetHelp(const char *help) {669LLDB_INSTRUMENT_VA(this, help);670671if (IsValid())672m_opaque_sp->SetHelp(help);673}674675void SBCommand::SetHelpLong(const char *help) {676LLDB_INSTRUMENT_VA(this, help);677678if (IsValid())679m_opaque_sp->SetHelpLong(help);680}681682lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name,683const char *help) {684LLDB_INSTRUMENT_VA(this, name, help);685686if (!IsValid())687return lldb::SBCommand();688if (!m_opaque_sp->IsMultiwordObject())689return lldb::SBCommand();690CommandObjectMultiword *new_command = new CommandObjectMultiword(691m_opaque_sp->GetCommandInterpreter(), name, help);692new_command->SetRemovable(true);693lldb::CommandObjectSP new_command_sp(new_command);694if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))695return lldb::SBCommand(new_command_sp);696return lldb::SBCommand();697}698699lldb::SBCommand SBCommand::AddCommand(const char *name,700lldb::SBCommandPluginInterface *impl,701const char *help) {702LLDB_INSTRUMENT_VA(this, name, impl, help);703return AddCommand(name, impl, help, /*syntax=*/nullptr,704/*auto_repeat_command=*/"");705}706707lldb::SBCommand SBCommand::AddCommand(const char *name,708lldb::SBCommandPluginInterface *impl,709const char *help, const char *syntax) {710LLDB_INSTRUMENT_VA(this, name, impl, help, syntax);711return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/"");712}713714lldb::SBCommand SBCommand::AddCommand(const char *name,715lldb::SBCommandPluginInterface *impl,716const char *help, const char *syntax,717const char *auto_repeat_command) {718LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command);719720if (!IsValid())721return lldb::SBCommand();722if (!m_opaque_sp->IsMultiwordObject())723return lldb::SBCommand();724lldb::CommandObjectSP new_command_sp;725new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(726m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax,727/*flags=*/0, auto_repeat_command);728if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))729return lldb::SBCommand(new_command_sp);730return lldb::SBCommand();731}732733uint32_t SBCommand::GetFlags() {734LLDB_INSTRUMENT_VA(this);735736return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);737}738739void SBCommand::SetFlags(uint32_t flags) {740LLDB_INSTRUMENT_VA(this, flags);741742if (IsValid())743m_opaque_sp->GetFlags().Set(flags);744}745746747