CommandObjectRegexCommand.cpp revision 314564
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
38314564Sdimbool CommandObjectRegexCommand::DoExecute(const char *command,
39314564Sdim                                          CommandReturnObject &result) {
40314564Sdim  if (command) {
41314564Sdim    EntryCollection::const_iterator pos, end = m_entries.end();
42314564Sdim    for (pos = m_entries.begin(); pos != end; ++pos) {
43314564Sdim      RegularExpression::Match regex_match(m_max_matches);
44254721Semaste
45314564Sdim      if (pos->regex.Execute(command, &regex_match)) {
46314564Sdim        std::string new_command(pos->command);
47314564Sdim        std::string match_str;
48314564Sdim        char percent_var[8];
49314564Sdim        size_t idx, percent_var_idx;
50314564Sdim        for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
51314564Sdim          if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
52314564Sdim            const int percent_var_len =
53314564Sdim                ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
54314564Sdim            for (idx = 0; (percent_var_idx = new_command.find(
55314564Sdim                               percent_var, idx)) != std::string::npos;) {
56314564Sdim              new_command.erase(percent_var_idx, percent_var_len);
57314564Sdim              new_command.insert(percent_var_idx, match_str);
58314564Sdim              idx += percent_var_idx + match_str.size();
59254721Semaste            }
60314564Sdim          }
61254721Semaste        }
62314564Sdim        // Interpret the new command and return this as the result!
63314564Sdim        if (m_interpreter.GetExpandRegexAliases())
64314564Sdim          result.GetOutputStream().Printf("%s\n", new_command.c_str());
65314564Sdim        // Pass in true for "no context switching".  The command that called us
66314564Sdim        // should have set up the context
67314564Sdim        // appropriately, we shouldn't have to redo that.
68314564Sdim        return m_interpreter.HandleCommand(new_command.c_str(),
69314564Sdim                                           eLazyBoolCalculate, result, nullptr,
70314564Sdim                                           true, true);
71314564Sdim      }
72254721Semaste    }
73254721Semaste    result.SetStatus(eReturnStatusFailed);
74314564Sdim    if (!GetSyntax().empty())
75314564Sdim      result.AppendError(GetSyntax());
76314564Sdim    else
77314564Sdim      result.AppendErrorWithFormat("Command contents '%s' failed to match any "
78314564Sdim                                   "regular expression in the '%s' regex "
79314564Sdim                                   "command.\n",
80314564Sdim                                   command, m_cmd_name.c_str());
81254721Semaste    return false;
82314564Sdim  }
83314564Sdim  result.AppendError("empty command passed to regular expression command");
84314564Sdim  result.SetStatus(eReturnStatusFailed);
85314564Sdim  return false;
86254721Semaste}
87254721Semaste
88314564Sdimbool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
89314564Sdim                                                const char *command_cstr) {
90314564Sdim  m_entries.resize(m_entries.size() + 1);
91314564Sdim  // Only add the regular expression if it compiles
92314564Sdim  if (m_entries.back().regex.Compile(
93314564Sdim          llvm::StringRef::withNullAsEmpty(re_cstr))) {
94314564Sdim    m_entries.back().command.assign(command_cstr);
95314564Sdim    return true;
96314564Sdim  }
97314564Sdim  // The regex didn't compile...
98314564Sdim  m_entries.pop_back();
99314564Sdim  return false;
100254721Semaste}
101254721Semaste
102314564Sdimint CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index,
103314564Sdim                                                int &cursor_char_position,
104314564Sdim                                                int match_start_point,
105314564Sdim                                                int max_return_elements,
106314564Sdim                                                bool &word_complete,
107314564Sdim                                                StringList &matches) {
108314564Sdim  if (m_completion_type_mask) {
109314564Sdim    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
110314564Sdim                               cursor_char_position);
111314564Sdim    CommandCompletions::InvokeCommonCompletionCallbacks(
112314564Sdim        GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(),
113314564Sdim        match_start_point, max_return_elements, nullptr, word_complete,
114314564Sdim        matches);
115314564Sdim    return matches.GetSize();
116314564Sdim  } else {
117314564Sdim    matches.Clear();
118314564Sdim    word_complete = false;
119314564Sdim  }
120314564Sdim  return 0;
121254721Semaste}
122