CommandObjectRegexCommand.cpp revision 314564
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(const char *command,
39                                          CommandReturnObject &result) {
40  if (command) {
41    EntryCollection::const_iterator pos, end = m_entries.end();
42    for (pos = m_entries.begin(); pos != end; ++pos) {
43      RegularExpression::Match regex_match(m_max_matches);
44
45      if (pos->regex.Execute(command, &regex_match)) {
46        std::string new_command(pos->command);
47        std::string match_str;
48        char percent_var[8];
49        size_t idx, percent_var_idx;
50        for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
51          if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
52            const int percent_var_len =
53                ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
54            for (idx = 0; (percent_var_idx = new_command.find(
55                               percent_var, idx)) != std::string::npos;) {
56              new_command.erase(percent_var_idx, percent_var_len);
57              new_command.insert(percent_var_idx, match_str);
58              idx += percent_var_idx + match_str.size();
59            }
60          }
61        }
62        // Interpret the new command and return this as the result!
63        if (m_interpreter.GetExpandRegexAliases())
64          result.GetOutputStream().Printf("%s\n", new_command.c_str());
65        // Pass in true for "no context switching".  The command that called us
66        // should have set up the context
67        // appropriately, we shouldn't have to redo that.
68        return m_interpreter.HandleCommand(new_command.c_str(),
69                                           eLazyBoolCalculate, result, nullptr,
70                                           true, true);
71      }
72    }
73    result.SetStatus(eReturnStatusFailed);
74    if (!GetSyntax().empty())
75      result.AppendError(GetSyntax());
76    else
77      result.AppendErrorWithFormat("Command contents '%s' failed to match any "
78                                   "regular expression in the '%s' regex "
79                                   "command.\n",
80                                   command, m_cmd_name.c_str());
81    return false;
82  }
83  result.AppendError("empty command passed to regular expression command");
84  result.SetStatus(eReturnStatusFailed);
85  return false;
86}
87
88bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
89                                                const char *command_cstr) {
90  m_entries.resize(m_entries.size() + 1);
91  // Only add the regular expression if it compiles
92  if (m_entries.back().regex.Compile(
93          llvm::StringRef::withNullAsEmpty(re_cstr))) {
94    m_entries.back().command.assign(command_cstr);
95    return true;
96  }
97  // The regex didn't compile...
98  m_entries.pop_back();
99  return false;
100}
101
102int CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index,
103                                                int &cursor_char_position,
104                                                int match_start_point,
105                                                int max_return_elements,
106                                                bool &word_complete,
107                                                StringList &matches) {
108  if (m_completion_type_mask) {
109    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
110                               cursor_char_position);
111    CommandCompletions::InvokeCommonCompletionCallbacks(
112        GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(),
113        match_start_point, max_return_elements, nullptr, word_complete,
114        matches);
115    return matches.GetSize();
116  } else {
117    matches.Clear();
118    word_complete = false;
119  }
120  return 0;
121}
122