19390b346SJonas Devlieghere //===-- CommandObjectRegexCommand.cpp -------------------------------------===// 29390b346SJonas Devlieghere // 39390b346SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49390b346SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information. 59390b346SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69390b346SJonas Devlieghere // 79390b346SJonas Devlieghere //===----------------------------------------------------------------------===// 89390b346SJonas Devlieghere 99390b346SJonas Devlieghere #include "CommandObjectRegexCommand.h" 109390b346SJonas Devlieghere #include "lldb/Interpreter/CommandInterpreter.h" 119390b346SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h" 129390b346SJonas Devlieghere 132a6dbedfSJonas Devlieghere #include "llvm/Support/Errc.h" 142a6dbedfSJonas Devlieghere #include "llvm/Support/Error.h" 152a6dbedfSJonas Devlieghere 169390b346SJonas Devlieghere using namespace lldb; 179390b346SJonas Devlieghere using namespace lldb_private; 189390b346SJonas Devlieghere 199390b346SJonas Devlieghere // CommandObjectRegexCommand constructor 209390b346SJonas Devlieghere CommandObjectRegexCommand::CommandObjectRegexCommand( 219390b346SJonas Devlieghere CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help, 2282352538SDave Lee llvm::StringRef syntax, uint32_t completion_type_mask, bool is_removable) 239390b346SJonas Devlieghere : CommandObjectRaw(interpreter, name, help, syntax), 2482352538SDave Lee m_completion_type_mask(completion_type_mask), 25abb0ed44SKazu Hirata m_is_removable(is_removable) {} 269390b346SJonas Devlieghere 279390b346SJonas Devlieghere // Destructor 28fd2433e1SJonas Devlieghere CommandObjectRegexCommand::~CommandObjectRegexCommand() = default; 299390b346SJonas Devlieghere 302a6dbedfSJonas Devlieghere llvm::Expected<std::string> CommandObjectRegexCommand::SubstituteVariables( 312a6dbedfSJonas Devlieghere llvm::StringRef input, 322a6dbedfSJonas Devlieghere const llvm::SmallVectorImpl<llvm::StringRef> &replacements) { 332a6dbedfSJonas Devlieghere std::string buffer; 342a6dbedfSJonas Devlieghere llvm::raw_string_ostream output(buffer); 352a6dbedfSJonas Devlieghere 362a6dbedfSJonas Devlieghere llvm::SmallVector<llvm::StringRef, 4> parts; 372a6dbedfSJonas Devlieghere input.split(parts, '%'); 382a6dbedfSJonas Devlieghere 392a6dbedfSJonas Devlieghere output << parts[0]; 402a6dbedfSJonas Devlieghere for (llvm::StringRef part : drop_begin(parts)) { 412a6dbedfSJonas Devlieghere size_t idx = 0; 422a6dbedfSJonas Devlieghere if (part.consumeInteger(10, idx)) 432a6dbedfSJonas Devlieghere output << '%'; 442a6dbedfSJonas Devlieghere else if (idx < replacements.size()) 452a6dbedfSJonas Devlieghere output << replacements[idx]; 462a6dbedfSJonas Devlieghere else 472a6dbedfSJonas Devlieghere return llvm::make_error<llvm::StringError>( 482a6dbedfSJonas Devlieghere llvm::formatv("%{0} is out of range: not enough arguments specified", 492a6dbedfSJonas Devlieghere idx), 502a6dbedfSJonas Devlieghere llvm::errc::invalid_argument); 512a6dbedfSJonas Devlieghere output << part; 522a6dbedfSJonas Devlieghere } 532a6dbedfSJonas Devlieghere 54*d7796855SYoungsuk Kim return buffer; 552a6dbedfSJonas Devlieghere } 562a6dbedfSJonas Devlieghere 5792d8a28cSPete Lawrence void CommandObjectRegexCommand::DoExecute(llvm::StringRef command, 589390b346SJonas Devlieghere CommandReturnObject &result) { 599390b346SJonas Devlieghere EntryCollection::const_iterator pos, end = m_entries.end(); 609390b346SJonas Devlieghere for (pos = m_entries.begin(); pos != end; ++pos) { 619390b346SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 4> matches; 629390b346SJonas Devlieghere if (pos->regex.Execute(command, &matches)) { 632a6dbedfSJonas Devlieghere llvm::Expected<std::string> new_command = 642a6dbedfSJonas Devlieghere SubstituteVariables(pos->command, matches); 652a6dbedfSJonas Devlieghere if (!new_command) { 662a6dbedfSJonas Devlieghere result.SetError(new_command.takeError()); 6792d8a28cSPete Lawrence return; 689390b346SJonas Devlieghere } 692a6dbedfSJonas Devlieghere 709390b346SJonas Devlieghere // Interpret the new command and return this as the result! 719390b346SJonas Devlieghere if (m_interpreter.GetExpandRegexAliases()) 722a6dbedfSJonas Devlieghere result.GetOutputStream().Printf("%s\n", new_command->c_str()); 738cc8b36fSJim Ingham // We don't have to pass an override_context here, as the command that 748cc8b36fSJim Ingham // called us should have set up the context appropriately. 755e0ee1b3SDave Lee bool force_repeat_command = true; 7692d8a28cSPete Lawrence m_interpreter.HandleCommand(new_command->c_str(), eLazyBoolNo, result, 7792d8a28cSPete Lawrence force_repeat_command); 7892d8a28cSPete Lawrence return; 799390b346SJonas Devlieghere } 809390b346SJonas Devlieghere } 819390b346SJonas Devlieghere result.SetStatus(eReturnStatusFailed); 829390b346SJonas Devlieghere if (!GetSyntax().empty()) 839390b346SJonas Devlieghere result.AppendError(GetSyntax()); 849390b346SJonas Devlieghere else 852a6dbedfSJonas Devlieghere result.GetErrorStream() << "Command contents '" << command 869390b346SJonas Devlieghere << "' failed to match any " 879390b346SJonas Devlieghere "regular expression in the '" 889390b346SJonas Devlieghere << m_cmd_name << "' regex "; 899390b346SJonas Devlieghere } 909390b346SJonas Devlieghere 919390b346SJonas Devlieghere bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr, 929390b346SJonas Devlieghere llvm::StringRef command_cstr) { 939390b346SJonas Devlieghere m_entries.resize(m_entries.size() + 1); 949390b346SJonas Devlieghere // Only add the regular expression if it compiles 959390b346SJonas Devlieghere m_entries.back().regex = RegularExpression(re_cstr); 969390b346SJonas Devlieghere if (m_entries.back().regex.IsValid()) { 979390b346SJonas Devlieghere m_entries.back().command = command_cstr.str(); 989390b346SJonas Devlieghere return true; 999390b346SJonas Devlieghere } 1009390b346SJonas Devlieghere // The regex didn't compile... 1019390b346SJonas Devlieghere m_entries.pop_back(); 1029390b346SJonas Devlieghere return false; 1039390b346SJonas Devlieghere } 1049390b346SJonas Devlieghere 1059390b346SJonas Devlieghere void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { 1069390b346SJonas Devlieghere if (m_completion_type_mask) { 1076a9c3e61SMed Ismail Bennani lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 1089390b346SJonas Devlieghere GetCommandInterpreter(), m_completion_type_mask, request, nullptr); 1099390b346SJonas Devlieghere } 1109390b346SJonas Devlieghere } 111