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 139390b346SJonas Devlieghere using namespace lldb; 149390b346SJonas Devlieghere using namespace lldb_private; 159390b346SJonas Devlieghere 169390b346SJonas Devlieghere // CommandObjectRegexCommand constructor 179390b346SJonas Devlieghere CommandObjectRegexCommand::CommandObjectRegexCommand( 189390b346SJonas Devlieghere CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help, 199390b346SJonas Devlieghere llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask, 209390b346SJonas Devlieghere bool is_removable) 219390b346SJonas Devlieghere : CommandObjectRaw(interpreter, name, help, syntax), 229390b346SJonas Devlieghere m_max_matches(max_matches), m_completion_type_mask(completion_type_mask), 23*abb0ed44SKazu Hirata m_is_removable(is_removable) {} 249390b346SJonas Devlieghere 259390b346SJonas Devlieghere // Destructor 26fd2433e1SJonas Devlieghere CommandObjectRegexCommand::~CommandObjectRegexCommand() = default; 279390b346SJonas Devlieghere 289390b346SJonas Devlieghere bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, 299390b346SJonas Devlieghere CommandReturnObject &result) { 309390b346SJonas Devlieghere EntryCollection::const_iterator pos, end = m_entries.end(); 319390b346SJonas Devlieghere for (pos = m_entries.begin(); pos != end; ++pos) { 329390b346SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 4> matches; 339390b346SJonas Devlieghere if (pos->regex.Execute(command, &matches)) { 349390b346SJonas Devlieghere std::string new_command(pos->command); 359390b346SJonas Devlieghere char percent_var[8]; 369390b346SJonas Devlieghere size_t idx, percent_var_idx; 379390b346SJonas Devlieghere for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) { 389390b346SJonas Devlieghere if (match_idx < matches.size()) { 399390b346SJonas Devlieghere const std::string match_str = matches[match_idx].str(); 409390b346SJonas Devlieghere const int percent_var_len = 419390b346SJonas Devlieghere ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx); 429390b346SJonas Devlieghere for (idx = 0; (percent_var_idx = new_command.find( 439390b346SJonas Devlieghere percent_var, idx)) != std::string::npos;) { 449390b346SJonas Devlieghere new_command.erase(percent_var_idx, percent_var_len); 459390b346SJonas Devlieghere new_command.insert(percent_var_idx, match_str); 463c454769SJim Ingham idx = percent_var_idx + match_str.size(); 479390b346SJonas Devlieghere } 489390b346SJonas Devlieghere } 499390b346SJonas Devlieghere } 509390b346SJonas Devlieghere // Interpret the new command and return this as the result! 519390b346SJonas Devlieghere if (m_interpreter.GetExpandRegexAliases()) 529390b346SJonas Devlieghere result.GetOutputStream().Printf("%s\n", new_command.c_str()); 539390b346SJonas Devlieghere // Pass in true for "no context switching". The command that called us 549390b346SJonas Devlieghere // should have set up the context appropriately, we shouldn't have to 559390b346SJonas Devlieghere // redo that. 5636de94cfSTatyana Krasnukha return m_interpreter.HandleCommand(new_command.c_str(), 5736de94cfSTatyana Krasnukha eLazyBoolCalculate, result); 589390b346SJonas Devlieghere } 599390b346SJonas Devlieghere } 609390b346SJonas Devlieghere result.SetStatus(eReturnStatusFailed); 619390b346SJonas Devlieghere if (!GetSyntax().empty()) 629390b346SJonas Devlieghere result.AppendError(GetSyntax()); 639390b346SJonas Devlieghere else 649390b346SJonas Devlieghere result.GetOutputStream() << "Command contents '" << command 659390b346SJonas Devlieghere << "' failed to match any " 669390b346SJonas Devlieghere "regular expression in the '" 679390b346SJonas Devlieghere << m_cmd_name << "' regex "; 689390b346SJonas Devlieghere return false; 699390b346SJonas Devlieghere } 709390b346SJonas Devlieghere 719390b346SJonas Devlieghere bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr, 729390b346SJonas Devlieghere llvm::StringRef command_cstr) { 739390b346SJonas Devlieghere m_entries.resize(m_entries.size() + 1); 749390b346SJonas Devlieghere // Only add the regular expression if it compiles 759390b346SJonas Devlieghere m_entries.back().regex = RegularExpression(re_cstr); 769390b346SJonas Devlieghere if (m_entries.back().regex.IsValid()) { 779390b346SJonas Devlieghere m_entries.back().command = command_cstr.str(); 789390b346SJonas Devlieghere return true; 799390b346SJonas Devlieghere } 809390b346SJonas Devlieghere // The regex didn't compile... 819390b346SJonas Devlieghere m_entries.pop_back(); 829390b346SJonas Devlieghere return false; 839390b346SJonas Devlieghere } 849390b346SJonas Devlieghere 859390b346SJonas Devlieghere void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { 869390b346SJonas Devlieghere if (m_completion_type_mask) { 879390b346SJonas Devlieghere CommandCompletions::InvokeCommonCompletionCallbacks( 889390b346SJonas Devlieghere GetCommandInterpreter(), m_completion_type_mask, request, nullptr); 899390b346SJonas Devlieghere } 909390b346SJonas Devlieghere } 91