CommandObjectRegexCommand.cpp revision 341825
1254721Semaste//===-- CommandObjectRegexCommand.cpp ---------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Interpreter/CommandObjectRegexCommand.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
17254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
18254721Semaste
19254721Semasteusing namespace lldb;
20254721Semasteusing namespace lldb_private;
21254721Semaste
22254721Semaste//----------------------------------------------------------------------
23254721Semaste// CommandObjectRegexCommand constructor
24254721Semaste//----------------------------------------------------------------------
25314564SdimCommandObjectRegexCommand::CommandObjectRegexCommand(
26314564Sdim    CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
27314564Sdim  llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask,
28314564Sdim    bool is_removable)
29314564Sdim    : CommandObjectRaw(interpreter, name, help, syntax),
30314564Sdim      m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
31314564Sdim      m_entries(), m_is_removable(is_removable) {}
32254721Semaste
33254721Semaste//----------------------------------------------------------------------
34254721Semaste// Destructor
35254721Semaste//----------------------------------------------------------------------
36314564SdimCommandObjectRegexCommand::~CommandObjectRegexCommand() {}
37254721Semaste
38341825Sdimbool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
39314564Sdim                                          CommandReturnObject &result) {
40341825Sdim  EntryCollection::const_iterator pos, end = m_entries.end();
41341825Sdim  for (pos = m_entries.begin(); pos != end; ++pos) {
42341825Sdim    RegularExpression::Match regex_match(m_max_matches);
43254721Semaste
44341825Sdim    if (pos->regex.Execute(command, &regex_match)) {
45341825Sdim      std::string new_command(pos->command);
46341825Sdim      std::string match_str;
47341825Sdim      char percent_var[8];
48341825Sdim      size_t idx, percent_var_idx;
49341825Sdim      for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
50341825Sdim        if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
51341825Sdim          const int percent_var_len =
52341825Sdim              ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
53341825Sdim          for (idx = 0; (percent_var_idx = new_command.find(
54341825Sdim                             percent_var, idx)) != std::string::npos;) {
55341825Sdim            new_command.erase(percent_var_idx, percent_var_len);
56341825Sdim            new_command.insert(percent_var_idx, match_str);
57341825Sdim            idx += percent_var_idx + match_str.size();
58314564Sdim          }
59254721Semaste        }
60314564Sdim      }
61341825Sdim      // Interpret the new command and return this as the result!
62341825Sdim      if (m_interpreter.GetExpandRegexAliases())
63341825Sdim        result.GetOutputStream().Printf("%s\n", new_command.c_str());
64341825Sdim      // Pass in true for "no context switching".  The command that called us
65341825Sdim      // should have set up the context appropriately, we shouldn't have to
66341825Sdim      // redo that.
67341825Sdim      return m_interpreter.HandleCommand(
68341825Sdim          new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
69254721Semaste    }
70314564Sdim  }
71314564Sdim  result.SetStatus(eReturnStatusFailed);
72341825Sdim  if (!GetSyntax().empty())
73341825Sdim    result.AppendError(GetSyntax());
74341825Sdim  else
75341825Sdim    result.GetOutputStream() << "Command contents '" << command
76341825Sdim                             << "' failed to match any "
77341825Sdim                                "regular expression in the '"
78341825Sdim                             << m_cmd_name << "' regex ";
79314564Sdim  return false;
80254721Semaste}
81254721Semaste
82314564Sdimbool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
83314564Sdim                                                const char *command_cstr) {
84314564Sdim  m_entries.resize(m_entries.size() + 1);
85314564Sdim  // Only add the regular expression if it compiles
86314564Sdim  if (m_entries.back().regex.Compile(
87314564Sdim          llvm::StringRef::withNullAsEmpty(re_cstr))) {
88314564Sdim    m_entries.back().command.assign(command_cstr);
89314564Sdim    return true;
90314564Sdim  }
91314564Sdim  // The regex didn't compile...
92314564Sdim  m_entries.pop_back();
93314564Sdim  return false;
94254721Semaste}
95254721Semaste
96341825Sdimint CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
97314564Sdim  if (m_completion_type_mask) {
98314564Sdim    CommandCompletions::InvokeCommonCompletionCallbacks(
99341825Sdim        GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
100341825Sdim    return request.GetNumberOfMatches();
101314564Sdim  } else {
102341825Sdim    request.SetWordComplete(false);
103314564Sdim  }
104314564Sdim  return 0;
105254721Semaste}
106