1 //===-- CommandObjectRegexCommand.cpp -------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectRegexCommand.h"
10 #include "lldb/Interpreter/CommandInterpreter.h"
11 #include "lldb/Interpreter/CommandReturnObject.h"
13 #include "llvm/Support/Errc.h"
14 #include "llvm/Support/Error.h"
17 using namespace lldb_private
;
19 // CommandObjectRegexCommand constructor
20 CommandObjectRegexCommand::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
) {}
28 CommandObjectRegexCommand::~CommandObjectRegexCommand() = default;
30 llvm::Expected
<std::string
> CommandObjectRegexCommand::SubstituteVariables(
31 llvm::StringRef input
,
32 const llvm::SmallVectorImpl
<llvm::StringRef
> &replacements
) {
34 llvm::raw_string_ostream
output(buffer
);
36 llvm::SmallVector
<llvm::StringRef
, 4> parts
;
37 input
.split(parts
, '%');
40 for (llvm::StringRef part
: drop_begin(parts
)) {
42 if (part
.consumeInteger(10, idx
))
44 else if (idx
< replacements
.size())
45 output
<< replacements
[idx
];
47 return llvm::make_error
<llvm::StringError
>(
48 llvm::formatv("%{0} is out of range: not enough arguments specified",
50 llvm::errc::invalid_argument
);
57 void 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
);
66 result
.SetError(new_command
.takeError());
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
);
81 result
.SetStatus(eReturnStatusFailed
);
82 if (!GetSyntax().empty())
83 result
.AppendError(GetSyntax());
85 result
.GetErrorStream() << "Command contents '" << command
86 << "' failed to match any "
87 "regular expression in the '"
88 << m_cmd_name
<< "' regex ";
91 bool 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 compiles
95 m_entries
.back().regex
= RegularExpression(re_cstr
);
96 if (m_entries
.back().regex
.IsValid()) {
97 m_entries
.back().command
= command_cstr
.str();
100 // The regex didn't compile...
101 m_entries
.pop_back();
105 void CommandObjectRegexCommand::HandleCompletion(CompletionRequest
&request
) {
106 if (m_completion_type_mask
) {
107 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
108 GetCommandInterpreter(), m_completion_type_mask
, request
, nullptr);