1254721Semaste//===-- CommandObjectRegexCommand.cpp ---------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include "lldb/Interpreter/CommandObjectRegexCommand.h" 10254721Semaste 11254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 12254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 13254721Semaste 14254721Semasteusing namespace lldb; 15254721Semasteusing namespace lldb_private; 16254721Semaste 17254721Semaste// CommandObjectRegexCommand constructor 18314564SdimCommandObjectRegexCommand::CommandObjectRegexCommand( 19314564Sdim CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help, 20314564Sdim llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask, 21314564Sdim bool is_removable) 22314564Sdim : CommandObjectRaw(interpreter, name, help, syntax), 23314564Sdim m_max_matches(max_matches), m_completion_type_mask(completion_type_mask), 24314564Sdim m_entries(), m_is_removable(is_removable) {} 25254721Semaste 26254721Semaste// Destructor 27314564SdimCommandObjectRegexCommand::~CommandObjectRegexCommand() {} 28254721Semaste 29341825Sdimbool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, 30314564Sdim CommandReturnObject &result) { 31341825Sdim EntryCollection::const_iterator pos, end = m_entries.end(); 32341825Sdim for (pos = m_entries.begin(); pos != end; ++pos) { 33360784Sdim llvm::SmallVector<llvm::StringRef, 4> matches; 34360784Sdim if (pos->regex.Execute(command, &matches)) { 35341825Sdim std::string new_command(pos->command); 36341825Sdim char percent_var[8]; 37341825Sdim size_t idx, percent_var_idx; 38341825Sdim for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) { 39360784Sdim if (match_idx < matches.size()) { 40360784Sdim const std::string match_str = matches[match_idx].str(); 41341825Sdim const int percent_var_len = 42341825Sdim ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx); 43341825Sdim for (idx = 0; (percent_var_idx = new_command.find( 44341825Sdim percent_var, idx)) != std::string::npos;) { 45341825Sdim new_command.erase(percent_var_idx, percent_var_len); 46341825Sdim new_command.insert(percent_var_idx, match_str); 47341825Sdim idx += percent_var_idx + match_str.size(); 48314564Sdim } 49254721Semaste } 50314564Sdim } 51341825Sdim // Interpret the new command and return this as the result! 52341825Sdim if (m_interpreter.GetExpandRegexAliases()) 53341825Sdim result.GetOutputStream().Printf("%s\n", new_command.c_str()); 54341825Sdim // Pass in true for "no context switching". The command that called us 55341825Sdim // should have set up the context appropriately, we shouldn't have to 56341825Sdim // redo that. 57341825Sdim return m_interpreter.HandleCommand( 58341825Sdim new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true); 59254721Semaste } 60314564Sdim } 61314564Sdim result.SetStatus(eReturnStatusFailed); 62341825Sdim if (!GetSyntax().empty()) 63341825Sdim result.AppendError(GetSyntax()); 64341825Sdim else 65341825Sdim result.GetOutputStream() << "Command contents '" << command 66341825Sdim << "' failed to match any " 67341825Sdim "regular expression in the '" 68341825Sdim << m_cmd_name << "' regex "; 69314564Sdim return false; 70254721Semaste} 71254721Semaste 72314564Sdimbool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr, 73314564Sdim const char *command_cstr) { 74314564Sdim m_entries.resize(m_entries.size() + 1); 75314564Sdim // Only add the regular expression if it compiles 76360784Sdim m_entries.back().regex = 77360784Sdim RegularExpression(llvm::StringRef::withNullAsEmpty(re_cstr)); 78360784Sdim if (m_entries.back().regex.IsValid()) { 79314564Sdim m_entries.back().command.assign(command_cstr); 80314564Sdim return true; 81314564Sdim } 82314564Sdim // The regex didn't compile... 83314564Sdim m_entries.pop_back(); 84314564Sdim return false; 85254721Semaste} 86254721Semaste 87360784Sdimvoid CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { 88314564Sdim if (m_completion_type_mask) { 89314564Sdim CommandCompletions::InvokeCommonCompletionCallbacks( 90341825Sdim GetCommandInterpreter(), m_completion_type_mask, request, nullptr); 91314564Sdim } 92254721Semaste} 93