CommandObjectRegexCommand.cpp revision 341825
1//===-- CommandObjectRegexCommand.cpp ---------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Interpreter/CommandObjectRegexCommand.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Interpreter/CommandInterpreter.h"
17#include "lldb/Interpreter/CommandReturnObject.h"
18
19using namespace lldb;
20using namespace lldb_private;
21
22//----------------------------------------------------------------------
23// CommandObjectRegexCommand constructor
24//----------------------------------------------------------------------
25CommandObjectRegexCommand::CommandObjectRegexCommand(
26    CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
27  llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask,
28    bool is_removable)
29    : CommandObjectRaw(interpreter, name, help, syntax),
30      m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
31      m_entries(), m_is_removable(is_removable) {}
32
33//----------------------------------------------------------------------
34// Destructor
35//----------------------------------------------------------------------
36CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
37
38bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
39                                          CommandReturnObject &result) {
40  EntryCollection::const_iterator pos, end = m_entries.end();
41  for (pos = m_entries.begin(); pos != end; ++pos) {
42    RegularExpression::Match regex_match(m_max_matches);
43
44    if (pos->regex.Execute(command, &regex_match)) {
45      std::string new_command(pos->command);
46      std::string match_str;
47      char percent_var[8];
48      size_t idx, percent_var_idx;
49      for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
50        if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
51          const int percent_var_len =
52              ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
53          for (idx = 0; (percent_var_idx = new_command.find(
54                             percent_var, idx)) != std::string::npos;) {
55            new_command.erase(percent_var_idx, percent_var_len);
56            new_command.insert(percent_var_idx, match_str);
57            idx += percent_var_idx + match_str.size();
58          }
59        }
60      }
61      // Interpret the new command and return this as the result!
62      if (m_interpreter.GetExpandRegexAliases())
63        result.GetOutputStream().Printf("%s\n", new_command.c_str());
64      // Pass in true for "no context switching".  The command that called us
65      // should have set up the context appropriately, we shouldn't have to
66      // redo that.
67      return m_interpreter.HandleCommand(
68          new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
69    }
70  }
71  result.SetStatus(eReturnStatusFailed);
72  if (!GetSyntax().empty())
73    result.AppendError(GetSyntax());
74  else
75    result.GetOutputStream() << "Command contents '" << command
76                             << "' failed to match any "
77                                "regular expression in the '"
78                             << m_cmd_name << "' regex ";
79  return false;
80}
81
82bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
83                                                const char *command_cstr) {
84  m_entries.resize(m_entries.size() + 1);
85  // Only add the regular expression if it compiles
86  if (m_entries.back().regex.Compile(
87          llvm::StringRef::withNullAsEmpty(re_cstr))) {
88    m_entries.back().command.assign(command_cstr);
89    return true;
90  }
91  // The regex didn't compile...
92  m_entries.pop_back();
93  return false;
94}
95
96int CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
97  if (m_completion_type_mask) {
98    CommandCompletions::InvokeCommonCompletionCallbacks(
99        GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
100    return request.GetNumberOfMatches();
101  } else {
102    request.SetWordComplete(false);
103  }
104  return 0;
105}
106