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