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