111 lines · cpp
1//===-- CommandObjectRegexCommand.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 "CommandObjectRegexCommand.h"10#include "lldb/Interpreter/CommandInterpreter.h"11#include "lldb/Interpreter/CommandReturnObject.h"12 13#include "llvm/Support/Errc.h"14#include "llvm/Support/Error.h"15 16using namespace lldb;17using namespace lldb_private;18 19// CommandObjectRegexCommand constructor20CommandObjectRegexCommand::CommandObjectRegexCommand(21 CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,22 llvm::StringRef syntax, uint32_t completion_type_mask, bool is_removable)23 : CommandObjectRaw(interpreter, name, help, syntax),24 m_completion_type_mask(completion_type_mask),25 m_is_removable(is_removable) {}26 27// Destructor28CommandObjectRegexCommand::~CommandObjectRegexCommand() = default;29 30llvm::Expected<std::string> CommandObjectRegexCommand::SubstituteVariables(31 llvm::StringRef input,32 const llvm::SmallVectorImpl<llvm::StringRef> &replacements) {33 std::string buffer;34 llvm::raw_string_ostream output(buffer);35 36 llvm::SmallVector<llvm::StringRef, 4> parts;37 input.split(parts, '%');38 39 output << parts[0];40 for (llvm::StringRef part : drop_begin(parts)) {41 size_t idx = 0;42 if (part.consumeInteger(10, idx))43 output << '%';44 else if (idx < replacements.size())45 output << replacements[idx];46 else47 return llvm::make_error<llvm::StringError>(48 llvm::formatv("%{0} is out of range: not enough arguments specified",49 idx),50 llvm::errc::invalid_argument);51 output << part;52 }53 54 return buffer;55}56 57void CommandObjectRegexCommand::DoExecute(llvm::StringRef command,58 CommandReturnObject &result) {59 EntryCollection::const_iterator pos, end = m_entries.end();60 for (pos = m_entries.begin(); pos != end; ++pos) {61 llvm::SmallVector<llvm::StringRef, 4> matches;62 if (pos->regex.Execute(command, &matches)) {63 llvm::Expected<std::string> new_command =64 SubstituteVariables(pos->command, matches);65 if (!new_command) {66 result.SetError(new_command.takeError());67 return;68 }69 70 // Interpret the new command and return this as the result!71 if (m_interpreter.GetExpandRegexAliases())72 result.GetOutputStream().Printf("%s\n", new_command->c_str());73 // We don't have to pass an override_context here, as the command that 74 // called us should have set up the context appropriately.75 bool force_repeat_command = true;76 m_interpreter.HandleCommand(new_command->c_str(), eLazyBoolNo, result,77 force_repeat_command);78 return;79 }80 }81 result.SetStatus(eReturnStatusFailed);82 if (!GetSyntax().empty())83 result.AppendError(GetSyntax());84 else85 result.GetErrorStream() << "Command contents '" << command86 << "' failed to match any "87 "regular expression in the '"88 << m_cmd_name << "' regex ";89}90 91bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr,92 llvm::StringRef command_cstr) {93 m_entries.resize(m_entries.size() + 1);94 // Only add the regular expression if it compiles95 m_entries.back().regex = RegularExpression(re_cstr);96 if (m_entries.back().regex.IsValid()) {97 m_entries.back().command = command_cstr.str();98 return true;99 }100 // The regex didn't compile...101 m_entries.pop_back();102 return false;103}104 105void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {106 if (m_completion_type_mask) {107 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(108 GetCommandInterpreter(), m_completion_type_mask, request, nullptr);109 }110}111