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/lldb-python.h"
11 
12 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Interpreter/CommandReturnObject.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 //----------------------------------------------------------------------
25 // CommandObjectRegexCommand constructor
26 //----------------------------------------------------------------------
27 CommandObjectRegexCommand::CommandObjectRegexCommand
28 (
29     CommandInterpreter &interpreter,
30     const char *name,
31     const char *help,
32     const char *syntax,
33     uint32_t max_matches,
34     uint32_t completion_type_mask,
35     bool is_removable
36 ) :
37     CommandObjectRaw (interpreter, name, help, syntax),
38     m_max_matches (max_matches),
39     m_completion_type_mask (completion_type_mask),
40     m_entries (),
41     m_is_removable (is_removable)
42 {
43 }
44 
45 //----------------------------------------------------------------------
46 // Destructor
47 //----------------------------------------------------------------------
48 CommandObjectRegexCommand::~CommandObjectRegexCommand()
49 {
50 }
51 
52 
53 bool
54 CommandObjectRegexCommand::DoExecute
55 (
56     const char *command,
57     CommandReturnObject &result
58 )
59 {
60     if (command)
61     {
62         EntryCollection::const_iterator pos, end = m_entries.end();
63         for (pos = m_entries.begin(); pos != end; ++pos)
64         {
65             RegularExpression::Match regex_match(m_max_matches);
66 
67             if (pos->regex.Execute (command, &regex_match))
68             {
69                 std::string new_command(pos->command);
70                 std::string match_str;
71                 char percent_var[8];
72                 size_t idx, percent_var_idx;
73                 for (uint32_t match_idx=1; match_idx <= m_max_matches; ++match_idx)
74                 {
75                     if (regex_match.GetMatchAtIndex (command, match_idx, match_str))
76                     {
77                         const int percent_var_len = ::snprintf (percent_var, sizeof(percent_var), "%%%u", match_idx);
78                         for (idx = 0; (percent_var_idx = new_command.find(percent_var, idx)) != std::string::npos; )
79                         {
80                             new_command.erase(percent_var_idx, percent_var_len);
81                             new_command.insert(percent_var_idx, match_str);
82                             idx += percent_var_idx + match_str.size();
83                         }
84                     }
85                 }
86                 // Interpret the new command and return this as the result!
87                 if (m_interpreter.GetExpandRegexAliases())
88                     result.GetOutputStream().Printf("%s\n", new_command.c_str());
89                 // Pass in true for "no context switching".  The command that called us should have set up the context
90                 // appropriately, we shouldn't have to redo that.
91                 return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
92             }
93         }
94         result.SetStatus(eReturnStatusFailed);
95         if (GetSyntax() != nullptr)
96             result.AppendError (GetSyntax());
97         else
98             result.AppendErrorWithFormat ("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
99                                           command,
100                                           m_cmd_name.c_str());
101         return false;
102     }
103     result.AppendError("empty command passed to regular expression command");
104     result.SetStatus(eReturnStatusFailed);
105     return false;
106 }
107 
108 
109 bool
110 CommandObjectRegexCommand::AddRegexCommand (const char *re_cstr, const char *command_cstr)
111 {
112     m_entries.resize(m_entries.size() + 1);
113     // Only add the regular expression if it compiles
114     if (m_entries.back().regex.Compile (re_cstr, REG_EXTENDED))
115     {
116         m_entries.back().command.assign (command_cstr);
117         return true;
118     }
119     // The regex didn't compile...
120     m_entries.pop_back();
121     return false;
122 }
123 
124 int
125 CommandObjectRegexCommand::HandleCompletion (Args &input,
126                                              int &cursor_index,
127                                              int &cursor_char_position,
128                                              int match_start_point,
129                                              int max_return_elements,
130                                              bool &word_complete,
131                                              StringList &matches)
132 {
133     if (m_completion_type_mask)
134     {
135         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
136         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
137                                                              m_completion_type_mask,
138                                                              completion_str.c_str(),
139                                                              match_start_point,
140                                                              max_return_elements,
141                                                              nullptr,
142                                                              word_complete,
143                                                              matches);
144         return matches.GetSize();
145     }
146     else
147     {
148         matches.Clear();
149         word_complete = false;
150     }
151     return 0;
152 }
153