| //===-- SBCommandInterpreter.cpp ------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "lldb/Utility/StructuredData.h" | |
| #include "lldb/lldb-types.h" | |
| #include "lldb/Interpreter/CommandInterpreter.h" | |
| #include "lldb/Interpreter/CommandObjectMultiword.h" | |
| #include "lldb/Interpreter/CommandReturnObject.h" | |
| #include "lldb/Target/Target.h" | |
| #include "lldb/Utility/Instrumentation.h" | |
| #include "lldb/Utility/Listener.h" | |
| #include "lldb/API/SBBroadcaster.h" | |
| #include "lldb/API/SBCommandInterpreter.h" | |
| #include "lldb/API/SBCommandInterpreterRunOptions.h" | |
| #include "lldb/API/SBCommandReturnObject.h" | |
| #include "lldb/API/SBEvent.h" | |
| #include "lldb/API/SBExecutionContext.h" | |
| #include "lldb/API/SBListener.h" | |
| #include "lldb/API/SBProcess.h" | |
| #include "lldb/API/SBStream.h" | |
| #include "lldb/API/SBStringList.h" | |
| #include "lldb/API/SBTarget.h" | |
| #include <memory> | |
| #include <optional> | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| namespace lldb_private { | |
| class CommandPluginInterfaceImplementation : public CommandObjectParsed { | |
| 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 = "") | |
| : CommandObjectParsed(interpreter, name, help, syntax, flags), | |
| m_backend(backend) { | |
| m_auto_repeat_command = | |
| auto_repeat_command == nullptr | |
| ? std::nullopt | |
| : std::optional<std::string>(auto_repeat_command); | |
| // We don't know whether any given command coming from this interface takes | |
| // arguments or not so here we're just disabling the basic args check. | |
| CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar}; | |
| m_arguments.push_back({none_arg}); | |
| } | |
| bool IsRemovable() const override { return true; } | |
| /// More documentation is available in lldb::CommandObject::GetRepeatCommand, | |
| /// but in short, if std::nullopt is returned, the previous command will be | |
| /// repeated, and if an empty string is returned, no commands will be | |
| /// executed. | |
| std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, | |
| uint32_t index) override { | |
| if (!m_auto_repeat_command) | |
| return std::nullopt; | |
| else | |
| return m_auto_repeat_command; | |
| } | |
| protected: | |
| void DoExecute(Args &command, CommandReturnObject &result) override { | |
| SBCommandReturnObject sb_return(result); | |
| SBCommandInterpreter sb_interpreter(&m_interpreter); | |
| SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); | |
| bool success = m_backend->DoExecute(debugger_sb, | |
| command.GetArgumentVector(), sb_return); | |
| // If the plugin command did not set its own status, infer it from the | |
| // boolean return value so that callers always see a defined status. | |
| if (result.GetStatus() == eReturnStatusInvalid) | |
| result.SetStatus(success ? eReturnStatusSuccessFinishResult | |
| : eReturnStatusFailed); | |
| } | |
| lldb::SBCommandPluginInterface *m_backend; | |
| std::optional<std::string> m_auto_repeat_command; | |
| }; | |
| } // namespace lldb_private | |
| SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() { | |
| LLDB_INSTRUMENT_VA(this); | |
| } | |
| SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) | |
| : m_opaque_ptr(interpreter) { | |
| LLDB_INSTRUMENT_VA(this, interpreter); | |
| } | |
| SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) | |
| : m_opaque_ptr(rhs.m_opaque_ptr) { | |
| LLDB_INSTRUMENT_VA(this, rhs); | |
| } | |
| SBCommandInterpreter::~SBCommandInterpreter() = default; | |
| const SBCommandInterpreter & | |
| SBCommandInterpreter::operator=(const SBCommandInterpreter &rhs) { | |
| LLDB_INSTRUMENT_VA(this, rhs); | |
| m_opaque_ptr = rhs.m_opaque_ptr; | |
| return *this; | |
| } | |
| bool SBCommandInterpreter::IsValid() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| return this->operator bool(); | |
| } | |
| SBCommandInterpreter::operator bool() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| return m_opaque_ptr != nullptr; | |
| } | |
| bool SBCommandInterpreter::CommandExists(const char *cmd) { | |
| LLDB_INSTRUMENT_VA(this, cmd); | |
| return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) | |
| : false); | |
| } | |
| bool SBCommandInterpreter::UserCommandExists(const char *cmd) { | |
| LLDB_INSTRUMENT_VA(this, cmd); | |
| return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->UserCommandExists(cmd) | |
| : false); | |
| } | |
| bool SBCommandInterpreter::AliasExists(const char *cmd) { | |
| LLDB_INSTRUMENT_VA(this, cmd); | |
| return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) | |
| : false); | |
| } | |
| bool SBCommandInterpreter::IsActive() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->IsActive() : false); | |
| } | |
| bool SBCommandInterpreter::WasInterrupted() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->GetDebugger().InterruptRequested() : false); | |
| } | |
| bool SBCommandInterpreter::InterruptCommand() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->InterruptCommand() : false); | |
| } | |
| const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { | |
| LLDB_INSTRUMENT_VA(this, ch); | |
| if (!IsValid()) | |
| return nullptr; | |
| return ConstString( | |
| m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch)) | |
| .GetCString(); | |
| } | |
| lldb::ReturnStatus | |
| SBCommandInterpreter::HandleCommand(const char *command_line, | |
| SBCommandReturnObject &result, | |
| bool add_to_history) { | |
| LLDB_INSTRUMENT_VA(this, command_line, result, add_to_history); | |
| SBExecutionContext sb_exe_ctx; | |
| return HandleCommand(command_line, sb_exe_ctx, result, add_to_history); | |
| } | |
| lldb::ReturnStatus SBCommandInterpreter::HandleCommand( | |
| const char *command_line, SBExecutionContext &override_context, | |
| SBCommandReturnObject &result, bool add_to_history) { | |
| LLDB_INSTRUMENT_VA(this, command_line, override_context, result, | |
| add_to_history); | |
| result.Clear(); | |
| if (command_line && IsValid()) { | |
| result.ref().SetInteractive(false); | |
| auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; | |
| if (override_context.get()) | |
| m_opaque_ptr->HandleCommand(command_line, do_add_to_history, | |
| override_context.get()->Lock(true), | |
| result.ref()); | |
| else | |
| m_opaque_ptr->HandleCommand(command_line, do_add_to_history, | |
| result.ref()); | |
| } else { | |
| result->AppendError( | |
| "SBCommandInterpreter or the command line is not valid"); | |
| } | |
| return result.GetStatus(); | |
| } | |
| void SBCommandInterpreter::HandleCommandsFromFile( | |
| lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context, | |
| lldb::SBCommandInterpreterRunOptions &options, | |
| lldb::SBCommandReturnObject result) { | |
| LLDB_INSTRUMENT_VA(this, file, override_context, options, result); | |
| if (!IsValid()) { | |
| result->AppendError("SBCommandInterpreter is not valid"); | |
| return; | |
| } | |
| if (!file.IsValid()) { | |
| SBStream s; | |
| file.GetDescription(s); | |
| result->AppendErrorWithFormat("File is not valid: %s", s.GetData()); | |
| } | |
| FileSpec tmp_spec = file.ref(); | |
| if (override_context.get()) | |
| m_opaque_ptr->HandleCommandsFromFile(tmp_spec, | |
| override_context.get()->Lock(true), | |
| options.ref(), result.ref()); | |
| else | |
| m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref()); | |
| } | |
| int SBCommandInterpreter::HandleCompletion( | |
| const char *current_line, const char *cursor, const char *last_char, | |
| int match_start_point, int max_return_elements, SBStringList &matches) { | |
| LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point, | |
| max_return_elements, matches); | |
| SBStringList dummy_descriptions; | |
| return HandleCompletionWithDescriptions( | |
| current_line, cursor, last_char, match_start_point, max_return_elements, | |
| matches, dummy_descriptions); | |
| } | |
| int SBCommandInterpreter::HandleCompletionWithDescriptions( | |
| const char *current_line, const char *cursor, const char *last_char, | |
| int match_start_point, int max_return_elements, SBStringList &matches, | |
| SBStringList &descriptions) { | |
| LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point, | |
| max_return_elements, matches, descriptions); | |
| // Sanity check the arguments that are passed in: cursor & last_char have to | |
| // be within the current_line. | |
| if (current_line == nullptr || cursor == nullptr || last_char == nullptr) | |
| return 0; | |
| if (cursor < current_line || last_char < current_line) | |
| return 0; | |
| size_t current_line_size = strlen(current_line); | |
| if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) || | |
| last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) | |
| return 0; | |
| if (!IsValid()) | |
| return 0; | |
| if (max_return_elements == 0) | |
| return 0; | |
| lldb_private::StringList lldb_matches, lldb_descriptions; | |
| CompletionResult result; | |
| CompletionRequest request(current_line, cursor - current_line, result); | |
| if (max_return_elements > 0) | |
| request.SetMaxReturnElements(max_return_elements); | |
| m_opaque_ptr->HandleCompletion(request); | |
| result.GetMatches(lldb_matches); | |
| result.GetDescriptions(lldb_descriptions); | |
| // limit the matches to the max_return_elements if necessary | |
| if (max_return_elements > 0 && | |
| lldb_matches.GetSize() > static_cast<size_t>(max_return_elements)) { | |
| lldb_matches.SetSize(max_return_elements); | |
| lldb_descriptions.SetSize(max_return_elements); | |
| } | |
| int number_of_matches = lldb_matches.GetSize(); | |
| // Make the result array indexed from 1 again by adding the 'common prefix' | |
| // of all completions as element 0. This is done to emulate the old API. | |
| if (request.GetParsedLine().GetArgumentCount() == 0) { | |
| // If we got an empty string, insert nothing. | |
| lldb_matches.InsertStringAtIndex(0, ""); | |
| lldb_descriptions.InsertStringAtIndex(0, ""); | |
| } else { | |
| // Now figure out if there is a common substring, and if so put that in | |
| // element 0, otherwise put an empty string in element 0. | |
| std::string command_partial_str = request.GetCursorArgumentPrefix().str(); | |
| std::string common_prefix = lldb_matches.LongestCommonPrefix(); | |
| const size_t partial_name_len = command_partial_str.size(); | |
| common_prefix.erase(0, partial_name_len); | |
| // If we matched a unique single command, add a space... Only do this if | |
| // the completer told us this was a complete word, however... | |
| if (lldb_matches.GetSize() == 1) { | |
| char quote_char = request.GetParsedArg().GetQuoteChar(); | |
| common_prefix = | |
| Args::EscapeLLDBCommandArgument(common_prefix, quote_char); | |
| if (request.GetParsedArg().IsQuoted()) | |
| common_prefix.push_back(quote_char); | |
| common_prefix.push_back(' '); | |
| } | |
| lldb_matches.InsertStringAtIndex(0, common_prefix.c_str()); | |
| lldb_descriptions.InsertStringAtIndex(0, ""); | |
| } | |
| SBStringList temp_matches_list(&lldb_matches); | |
| matches.AppendList(temp_matches_list); | |
| SBStringList temp_descriptions_list(&lldb_descriptions); | |
| descriptions.AppendList(temp_descriptions_list); | |
| return number_of_matches; | |
| } | |
| int SBCommandInterpreter::HandleCompletionWithDescriptions( | |
| const char *current_line, uint32_t cursor_pos, int match_start_point, | |
| int max_return_elements, SBStringList &matches, | |
| SBStringList &descriptions) { | |
| LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point, | |
| max_return_elements, matches, descriptions); | |
| const char *cursor = current_line + cursor_pos; | |
| const char *last_char = current_line + strlen(current_line); | |
| return HandleCompletionWithDescriptions( | |
| current_line, cursor, last_char, match_start_point, max_return_elements, | |
| matches, descriptions); | |
| } | |
| int SBCommandInterpreter::HandleCompletion(const char *current_line, | |
| uint32_t cursor_pos, | |
| int match_start_point, | |
| int max_return_elements, | |
| lldb::SBStringList &matches) { | |
| LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point, | |
| max_return_elements, matches); | |
| const char *cursor = current_line + cursor_pos; | |
| const char *last_char = current_line + strlen(current_line); | |
| return HandleCompletion(current_line, cursor, last_char, match_start_point, | |
| max_return_elements, matches); | |
| } | |
| bool SBCommandInterpreter::HasCommands() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->HasCommands() : false); | |
| } | |
| bool SBCommandInterpreter::HasAliases() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->HasAliases() : false); | |
| } | |
| bool SBCommandInterpreter::HasAliasOptions() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); | |
| } | |
| bool SBCommandInterpreter::IsInteractive() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->IsInteractive() : false); | |
| } | |
| SBProcess SBCommandInterpreter::GetProcess() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBProcess sb_process; | |
| ProcessSP process_sp; | |
| if (IsValid()) { | |
| TargetSP target_sp(m_opaque_ptr->GetSelectedTarget()); | |
| if (target_sp) { | |
| TargetAPIMutex api_lock = target_sp->GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| process_sp = target_sp->GetProcessSP(); | |
| sb_process.SetSP(process_sp); | |
| } | |
| } | |
| return sb_process; | |
| } | |
| SBDebugger SBCommandInterpreter::GetDebugger() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBDebugger sb_debugger; | |
| if (IsValid()) | |
| sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); | |
| return sb_debugger; | |
| } | |
| bool SBCommandInterpreter::GetPromptOnQuit() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); | |
| } | |
| void SBCommandInterpreter::SetPromptOnQuit(bool b) { | |
| LLDB_INSTRUMENT_VA(this, b); | |
| if (IsValid()) | |
| m_opaque_ptr->SetPromptOnQuit(b); | |
| } | |
| void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) { | |
| LLDB_INSTRUMENT_VA(this, allow); | |
| if (m_opaque_ptr) | |
| m_opaque_ptr->AllowExitCodeOnQuit(allow); | |
| } | |
| bool SBCommandInterpreter::HasCustomQuitExitCode() { | |
| LLDB_INSTRUMENT_VA(this); | |
| bool exited = false; | |
| if (m_opaque_ptr) | |
| m_opaque_ptr->GetQuitExitCode(exited); | |
| return exited; | |
| } | |
| int SBCommandInterpreter::GetQuitStatus() { | |
| LLDB_INSTRUMENT_VA(this); | |
| bool exited = false; | |
| return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0); | |
| } | |
| void SBCommandInterpreter::ResolveCommand(const char *command_line, | |
| SBCommandReturnObject &result) { | |
| LLDB_INSTRUMENT_VA(this, command_line, result); | |
| result.Clear(); | |
| if (command_line && IsValid()) { | |
| m_opaque_ptr->ResolveCommand(command_line, result.ref()); | |
| } else { | |
| result->AppendError( | |
| "SBCommandInterpreter or the command line is not valid"); | |
| } | |
| } | |
| CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; } | |
| CommandInterpreter &SBCommandInterpreter::ref() { | |
| assert(m_opaque_ptr); | |
| return *m_opaque_ptr; | |
| } | |
| void SBCommandInterpreter::reset( | |
| lldb_private::CommandInterpreter *interpreter) { | |
| m_opaque_ptr = interpreter; | |
| } | |
| void SBCommandInterpreter::SourceInitFileInGlobalDirectory( | |
| SBCommandReturnObject &result) { | |
| LLDB_INSTRUMENT_VA(this, result); | |
| result.Clear(); | |
| if (IsValid()) { | |
| TargetSP target_sp(m_opaque_ptr->GetSelectedTarget()); | |
| TargetAPIMutex api_lock; | |
| std::unique_lock<TargetAPIMutex> guard; | |
| if (target_sp) { | |
| api_lock = TargetAPIMutex(target_sp->GetAPIMutex()); | |
| guard = std::unique_lock<TargetAPIMutex>(api_lock); | |
| } | |
| m_opaque_ptr->SourceInitFileGlobal(result.ref()); | |
| } else { | |
| result->AppendError("SBCommandInterpreter is not valid"); | |
| } | |
| } | |
| void SBCommandInterpreter::SourceInitFileInHomeDirectory( | |
| SBCommandReturnObject &result) { | |
| LLDB_INSTRUMENT_VA(this, result); | |
| SourceInitFileInHomeDirectory(result, /*is_repl=*/false); | |
| } | |
| void SBCommandInterpreter::SourceInitFileInHomeDirectory( | |
| SBCommandReturnObject &result, bool is_repl) { | |
| LLDB_INSTRUMENT_VA(this, result, is_repl); | |
| result.Clear(); | |
| if (IsValid()) { | |
| TargetSP target_sp(m_opaque_ptr->GetSelectedTarget()); | |
| TargetAPIMutex api_lock; | |
| std::unique_lock<TargetAPIMutex> guard; | |
| if (target_sp) { | |
| api_lock = TargetAPIMutex(target_sp->GetAPIMutex()); | |
| guard = std::unique_lock<TargetAPIMutex>(api_lock); | |
| } | |
| m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl); | |
| } else { | |
| result->AppendError("SBCommandInterpreter is not valid"); | |
| } | |
| } | |
| void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory( | |
| SBCommandReturnObject &result) { | |
| LLDB_INSTRUMENT_VA(this, result); | |
| result.Clear(); | |
| if (IsValid()) { | |
| TargetSP target_sp(m_opaque_ptr->GetSelectedTarget()); | |
| TargetAPIMutex api_lock; | |
| std::unique_lock<TargetAPIMutex> guard; | |
| if (target_sp) { | |
| api_lock = TargetAPIMutex(target_sp->GetAPIMutex()); | |
| guard = std::unique_lock<TargetAPIMutex>(api_lock); | |
| } | |
| m_opaque_ptr->SourceInitFileCwd(result.ref()); | |
| } else { | |
| result->AppendError("SBCommandInterpreter is not valid"); | |
| } | |
| } | |
| SBBroadcaster SBCommandInterpreter::GetBroadcaster() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBBroadcaster broadcaster(m_opaque_ptr, false); | |
| return broadcaster; | |
| } | |
| const char *SBCommandInterpreter::GetBroadcasterClass() { | |
| LLDB_INSTRUMENT(); | |
| return ConstString(CommandInterpreter::GetStaticBroadcasterClass()) | |
| .AsCString(nullptr); | |
| } | |
| const char *SBCommandInterpreter::GetArgumentTypeAsCString( | |
| const lldb::CommandArgumentType arg_type) { | |
| LLDB_INSTRUMENT_VA(arg_type); | |
| return ConstString(CommandObject::GetArgumentTypeAsCString(arg_type)) | |
| .GetCString(); | |
| } | |
| const char *SBCommandInterpreter::GetArgumentDescriptionAsCString( | |
| const lldb::CommandArgumentType arg_type) { | |
| LLDB_INSTRUMENT_VA(arg_type); | |
| return ConstString(CommandObject::GetArgumentDescriptionAsCString(arg_type)) | |
| .GetCString(); | |
| } | |
| bool SBCommandInterpreter::EventIsCommandInterpreterEvent( | |
| const lldb::SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| return event.GetBroadcasterClass() == | |
| SBCommandInterpreter::GetBroadcasterClass(); | |
| } | |
| bool SBCommandInterpreter::SetCommandOverrideCallback( | |
| const char *command_name, lldb::CommandOverrideCallback callback, | |
| void *baton) { | |
| LLDB_INSTRUMENT_VA(this, command_name, callback, baton); | |
| if (command_name && command_name[0] && IsValid()) { | |
| llvm::StringRef command_name_str = command_name; | |
| CommandObject *cmd_obj = | |
| m_opaque_ptr->GetCommandObjectForCommand(command_name_str); | |
| if (cmd_obj) { | |
| assert(command_name_str.empty()); | |
| cmd_obj->SetOverrideCallback(callback, baton); | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| SBStructuredData SBCommandInterpreter::GetStatistics() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBStructuredData data; | |
| if (!IsValid()) | |
| return data; | |
| std::string json_str = | |
| llvm::formatv("{0:2}", m_opaque_ptr->GetStatistics()).str(); | |
| data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str)); | |
| return data; | |
| } | |
| SBStructuredData SBCommandInterpreter::GetTranscript() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBStructuredData data; | |
| if (IsValid()) | |
| // A deep copy is performed by `std::make_shared` on the | |
| // `StructuredData::Array`, via its implicitly-declared copy constructor. | |
| // This ensures thread-safety between the user changing the returned | |
| // `SBStructuredData` and the `CommandInterpreter` changing its internal | |
| // `m_transcript`. | |
| data.m_impl_up->SetObjectSP( | |
| std::make_shared<StructuredData::Array>(m_opaque_ptr->GetTranscript())); | |
| return data; | |
| } | |
| lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name, | |
| const char *help) { | |
| LLDB_INSTRUMENT_VA(this, name, help); | |
| lldb::CommandObjectSP new_command_sp( | |
| new CommandObjectMultiword(*m_opaque_ptr, name, help)); | |
| new_command_sp->GetAsMultiwordCommand()->SetRemovable(true); | |
| Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true); | |
| if (add_error.Success()) | |
| return lldb::SBCommand(new_command_sp); | |
| return lldb::SBCommand(); | |
| } | |
| lldb::SBCommand SBCommandInterpreter::AddCommand( | |
| const char *name, lldb::SBCommandPluginInterface *impl, const char *help) { | |
| LLDB_INSTRUMENT_VA(this, name, impl, help); | |
| return AddCommand(name, impl, help, /*syntax=*/nullptr, | |
| /*auto_repeat_command=*/""); | |
| } | |
| lldb::SBCommand | |
| SBCommandInterpreter::AddCommand(const char *name, | |
| lldb::SBCommandPluginInterface *impl, | |
| const char *help, const char *syntax) { | |
| LLDB_INSTRUMENT_VA(this, name, impl, help, syntax); | |
| return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""); | |
| } | |
| lldb::SBCommand SBCommandInterpreter::AddCommand( | |
| const char *name, lldb::SBCommandPluginInterface *impl, const char *help, | |
| const char *syntax, const char *auto_repeat_command) { | |
| LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command); | |
| lldb::CommandObjectSP new_command_sp; | |
| new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>( | |
| *m_opaque_ptr, name, impl, help, syntax, /*flags=*/0, | |
| auto_repeat_command); | |
| Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true); | |
| if (add_error.Success()) | |
| return lldb::SBCommand(new_command_sp); | |
| return lldb::SBCommand(); | |
| } | |
| SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); } | |
| SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {} | |
| bool SBCommand::IsValid() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return this->operator bool(); | |
| } | |
| SBCommand::operator bool() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| return m_opaque_sp.get() != nullptr; | |
| } | |
| const char *SBCommand::GetName() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() | |
| ? ConstString(m_opaque_sp->GetCommandName()).AsCString(nullptr) | |
| : nullptr); | |
| } | |
| const char *SBCommand::GetHelp() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString(nullptr) | |
| : nullptr); | |
| } | |
| const char *SBCommand::GetHelpLong() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString(nullptr) | |
| : nullptr); | |
| } | |
| void SBCommand::SetHelp(const char *help) { | |
| LLDB_INSTRUMENT_VA(this, help); | |
| if (IsValid()) | |
| m_opaque_sp->SetHelp(help); | |
| } | |
| void SBCommand::SetHelpLong(const char *help) { | |
| LLDB_INSTRUMENT_VA(this, help); | |
| if (IsValid()) | |
| m_opaque_sp->SetHelpLong(help); | |
| } | |
| lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name, | |
| const char *help) { | |
| LLDB_INSTRUMENT_VA(this, name, help); | |
| if (!IsValid()) | |
| return lldb::SBCommand(); | |
| if (!m_opaque_sp->IsMultiwordObject()) | |
| return lldb::SBCommand(); | |
| CommandObjectMultiword *new_command = new CommandObjectMultiword( | |
| m_opaque_sp->GetCommandInterpreter(), name, help); | |
| new_command->SetRemovable(true); | |
| lldb::CommandObjectSP new_command_sp(new_command); | |
| if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) | |
| return lldb::SBCommand(new_command_sp); | |
| return lldb::SBCommand(); | |
| } | |
| lldb::SBCommand SBCommand::AddCommand(const char *name, | |
| lldb::SBCommandPluginInterface *impl, | |
| const char *help) { | |
| LLDB_INSTRUMENT_VA(this, name, impl, help); | |
| return AddCommand(name, impl, help, /*syntax=*/nullptr, | |
| /*auto_repeat_command=*/""); | |
| } | |
| lldb::SBCommand SBCommand::AddCommand(const char *name, | |
| lldb::SBCommandPluginInterface *impl, | |
| const char *help, const char *syntax) { | |
| LLDB_INSTRUMENT_VA(this, name, impl, help, syntax); | |
| return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""); | |
| } | |
| lldb::SBCommand SBCommand::AddCommand(const char *name, | |
| lldb::SBCommandPluginInterface *impl, | |
| const char *help, const char *syntax, | |
| const char *auto_repeat_command) { | |
| LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command); | |
| if (!IsValid()) | |
| return lldb::SBCommand(); | |
| if (!m_opaque_sp->IsMultiwordObject()) | |
| return lldb::SBCommand(); | |
| lldb::CommandObjectSP new_command_sp; | |
| new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>( | |
| m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax, | |
| /*flags=*/0, auto_repeat_command); | |
| if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) | |
| return lldb::SBCommand(new_command_sp); | |
| return lldb::SBCommand(); | |
| } | |
| uint32_t SBCommand::GetFlags() { | |
| LLDB_INSTRUMENT_VA(this); | |
| return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); | |
| } | |
| void SBCommand::SetFlags(uint32_t flags) { | |
| LLDB_INSTRUMENT_VA(this, flags); | |
| if (IsValid()) | |
| m_opaque_sp->GetFlags().Set(flags); | |
| } | |
| void SBCommandInterpreter::SetPrintCallback( | |
| lldb::SBCommandPrintCallback callback, void *baton) { | |
| LLDB_INSTRUMENT_VA(this, callback, baton); | |
| if (m_opaque_ptr) | |
| m_opaque_ptr->SetPrintCallback( | |
| [callback, baton](lldb_private::CommandReturnObject &result) { | |
| SBCommandReturnObject sb_result(result); | |
| return callback(sb_result, baton); | |
| }); | |
| } |