llvm-capstone/lldb/source/Commands/CommandObjectRegexCommand.cpp
Pavel Labath 122a4ebde3 Revert "[lldb] Make CommandInterpreter's execution context the same as debugger's one."
This reverts commit a01b26fb51c710a3a8ef88cc83b0701461f5b9ab, because it
breaks the "finish" command in some way -- the command does not
terminate after it steps out, but continues running the target. The
exact blast radius is not clear, but it at least affects the usage of
the "finish" command in TestGuiBasicDebug.py. The error is *not*
gui-related, as the same issue can be reproduced by running the same
steps outside of the gui.

There is some kind of a race going on, as the test fails only 20% of the
time on the buildbot.
2020-12-17 17:47:53 +01:00

91 lines
3.7 KiB
C++

//===-- CommandObjectRegexCommand.cpp -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CommandObjectRegexCommand.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
using namespace lldb;
using namespace lldb_private;
// CommandObjectRegexCommand constructor
CommandObjectRegexCommand::CommandObjectRegexCommand(
CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask,
bool is_removable)
: CommandObjectRaw(interpreter, name, help, syntax),
m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
m_entries(), m_is_removable(is_removable) {}
// Destructor
CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
EntryCollection::const_iterator pos, end = m_entries.end();
for (pos = m_entries.begin(); pos != end; ++pos) {
llvm::SmallVector<llvm::StringRef, 4> matches;
if (pos->regex.Execute(command, &matches)) {
std::string new_command(pos->command);
char percent_var[8];
size_t idx, percent_var_idx;
for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
if (match_idx < matches.size()) {
const std::string match_str = matches[match_idx].str();
const int percent_var_len =
::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
for (idx = 0; (percent_var_idx = new_command.find(
percent_var, idx)) != std::string::npos;) {
new_command.erase(percent_var_idx, percent_var_len);
new_command.insert(percent_var_idx, match_str);
idx += percent_var_idx + match_str.size();
}
}
}
// Interpret the new command and return this as the result!
if (m_interpreter.GetExpandRegexAliases())
result.GetOutputStream().Printf("%s\n", new_command.c_str());
// Pass in true for "no context switching". The command that called us
// should have set up the context appropriately, we shouldn't have to
// redo that.
return m_interpreter.HandleCommand(
new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
}
}
result.SetStatus(eReturnStatusFailed);
if (!GetSyntax().empty())
result.AppendError(GetSyntax());
else
result.GetOutputStream() << "Command contents '" << command
<< "' failed to match any "
"regular expression in the '"
<< m_cmd_name << "' regex ";
return false;
}
bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr,
llvm::StringRef command_cstr) {
m_entries.resize(m_entries.size() + 1);
// Only add the regular expression if it compiles
m_entries.back().regex = RegularExpression(re_cstr);
if (m_entries.back().regex.IsValid()) {
m_entries.back().command = command_cstr.str();
return true;
}
// The regex didn't compile...
m_entries.pop_back();
return false;
}
void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
if (m_completion_type_mask) {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
}
}