1ac7ddfbfSEd Maste //===-- CommandObjectRegexCommand.cpp ---------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandObjectRegexCommand.h"
11ac7ddfbfSEd Maste
12ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
13ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
14ac7ddfbfSEd Maste
15ac7ddfbfSEd Maste using namespace lldb;
16ac7ddfbfSEd Maste using namespace lldb_private;
17ac7ddfbfSEd Maste
18ac7ddfbfSEd Maste //----------------------------------------------------------------------
19ac7ddfbfSEd Maste // CommandObjectRegexCommand constructor
20ac7ddfbfSEd Maste //----------------------------------------------------------------------
CommandObjectRegexCommand(CommandInterpreter & interpreter,llvm::StringRef name,llvm::StringRef help,llvm::StringRef syntax,uint32_t max_matches,uint32_t completion_type_mask,bool is_removable)21435933ddSDimitry Andric CommandObjectRegexCommand::CommandObjectRegexCommand(
22435933ddSDimitry Andric CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
23435933ddSDimitry Andric llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask,
24435933ddSDimitry Andric bool is_removable)
25435933ddSDimitry Andric : CommandObjectRaw(interpreter, name, help, syntax),
26435933ddSDimitry Andric m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
27435933ddSDimitry Andric m_entries(), m_is_removable(is_removable) {}
28ac7ddfbfSEd Maste
29ac7ddfbfSEd Maste //----------------------------------------------------------------------
30ac7ddfbfSEd Maste // Destructor
31ac7ddfbfSEd Maste //----------------------------------------------------------------------
~CommandObjectRegexCommand()32435933ddSDimitry Andric CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
33ac7ddfbfSEd Maste
DoExecute(llvm::StringRef command,CommandReturnObject & result)34*4ba319b5SDimitry Andric bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
35435933ddSDimitry Andric CommandReturnObject &result) {
36ac7ddfbfSEd Maste EntryCollection::const_iterator pos, end = m_entries.end();
37435933ddSDimitry Andric for (pos = m_entries.begin(); pos != end; ++pos) {
38ac7ddfbfSEd Maste RegularExpression::Match regex_match(m_max_matches);
39ac7ddfbfSEd Maste
40435933ddSDimitry Andric if (pos->regex.Execute(command, ®ex_match)) {
41ac7ddfbfSEd Maste std::string new_command(pos->command);
42ac7ddfbfSEd Maste std::string match_str;
43ac7ddfbfSEd Maste char percent_var[8];
44ac7ddfbfSEd Maste size_t idx, percent_var_idx;
45435933ddSDimitry Andric for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
46435933ddSDimitry Andric if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
47435933ddSDimitry Andric const int percent_var_len =
48435933ddSDimitry Andric ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
49435933ddSDimitry Andric for (idx = 0; (percent_var_idx = new_command.find(
50435933ddSDimitry Andric percent_var, idx)) != std::string::npos;) {
51ac7ddfbfSEd Maste new_command.erase(percent_var_idx, percent_var_len);
52ac7ddfbfSEd Maste new_command.insert(percent_var_idx, match_str);
53ac7ddfbfSEd Maste idx += percent_var_idx + match_str.size();
54ac7ddfbfSEd Maste }
55ac7ddfbfSEd Maste }
56ac7ddfbfSEd Maste }
57ac7ddfbfSEd Maste // Interpret the new command and return this as the result!
58ac7ddfbfSEd Maste if (m_interpreter.GetExpandRegexAliases())
59ac7ddfbfSEd Maste result.GetOutputStream().Printf("%s\n", new_command.c_str());
60435933ddSDimitry Andric // Pass in true for "no context switching". The command that called us
61*4ba319b5SDimitry Andric // should have set up the context appropriately, we shouldn't have to
62*4ba319b5SDimitry Andric // redo that.
63*4ba319b5SDimitry Andric return m_interpreter.HandleCommand(
64*4ba319b5SDimitry Andric new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
65ac7ddfbfSEd Maste }
66ac7ddfbfSEd Maste }
67ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
68435933ddSDimitry Andric if (!GetSyntax().empty())
69ac7ddfbfSEd Maste result.AppendError(GetSyntax());
70ac7ddfbfSEd Maste else
71*4ba319b5SDimitry Andric result.GetOutputStream() << "Command contents '" << command
72*4ba319b5SDimitry Andric << "' failed to match any "
73*4ba319b5SDimitry Andric "regular expression in the '"
74*4ba319b5SDimitry Andric << m_cmd_name << "' regex ";
75ac7ddfbfSEd Maste return false;
76ac7ddfbfSEd Maste }
77ac7ddfbfSEd Maste
AddRegexCommand(const char * re_cstr,const char * command_cstr)78435933ddSDimitry Andric bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
79435933ddSDimitry Andric const char *command_cstr) {
80ac7ddfbfSEd Maste m_entries.resize(m_entries.size() + 1);
81ac7ddfbfSEd Maste // Only add the regular expression if it compiles
82435933ddSDimitry Andric if (m_entries.back().regex.Compile(
83435933ddSDimitry Andric llvm::StringRef::withNullAsEmpty(re_cstr))) {
84ac7ddfbfSEd Maste m_entries.back().command.assign(command_cstr);
85ac7ddfbfSEd Maste return true;
86ac7ddfbfSEd Maste }
87ac7ddfbfSEd Maste // The regex didn't compile...
88ac7ddfbfSEd Maste m_entries.pop_back();
89ac7ddfbfSEd Maste return false;
90ac7ddfbfSEd Maste }
91ac7ddfbfSEd Maste
HandleCompletion(CompletionRequest & request)92*4ba319b5SDimitry Andric int CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
93435933ddSDimitry Andric if (m_completion_type_mask) {
94435933ddSDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
95*4ba319b5SDimitry Andric GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
96*4ba319b5SDimitry Andric return request.GetNumberOfMatches();
97435933ddSDimitry Andric } else {
98*4ba319b5SDimitry Andric request.SetWordComplete(false);
99ac7ddfbfSEd Maste }
100ac7ddfbfSEd Maste return 0;
101ac7ddfbfSEd Maste }
102