1ac7ddfbfSEd Maste //===-- CommandObjectRegexCommand.cpp ---------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandObjectRegexCommand.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
13ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
14ac7ddfbfSEd Maste 
15ac7ddfbfSEd Maste using namespace lldb;
16ac7ddfbfSEd Maste using namespace lldb_private;
17ac7ddfbfSEd Maste 
18ac7ddfbfSEd Maste //----------------------------------------------------------------------
19ac7ddfbfSEd Maste // CommandObjectRegexCommand constructor
20ac7ddfbfSEd Maste //----------------------------------------------------------------------
CommandObjectRegexCommand(CommandInterpreter & interpreter,llvm::StringRef name,llvm::StringRef help,llvm::StringRef syntax,uint32_t max_matches,uint32_t completion_type_mask,bool is_removable)21435933ddSDimitry Andric CommandObjectRegexCommand::CommandObjectRegexCommand(
22435933ddSDimitry Andric     CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
23435933ddSDimitry Andric   llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask,
24435933ddSDimitry Andric     bool is_removable)
25435933ddSDimitry Andric     : CommandObjectRaw(interpreter, name, help, syntax),
26435933ddSDimitry Andric       m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
27435933ddSDimitry Andric       m_entries(), m_is_removable(is_removable) {}
28ac7ddfbfSEd Maste 
29ac7ddfbfSEd Maste //----------------------------------------------------------------------
30ac7ddfbfSEd Maste // Destructor
31ac7ddfbfSEd Maste //----------------------------------------------------------------------
~CommandObjectRegexCommand()32435933ddSDimitry Andric CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
33ac7ddfbfSEd Maste 
DoExecute(llvm::StringRef command,CommandReturnObject & result)34*4ba319b5SDimitry Andric bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
35435933ddSDimitry Andric                                           CommandReturnObject &result) {
36ac7ddfbfSEd Maste   EntryCollection::const_iterator pos, end = m_entries.end();
37435933ddSDimitry Andric   for (pos = m_entries.begin(); pos != end; ++pos) {
38ac7ddfbfSEd Maste     RegularExpression::Match regex_match(m_max_matches);
39ac7ddfbfSEd Maste 
40435933ddSDimitry Andric     if (pos->regex.Execute(command, &regex_match)) {
41ac7ddfbfSEd Maste       std::string new_command(pos->command);
42ac7ddfbfSEd Maste       std::string match_str;
43ac7ddfbfSEd Maste       char percent_var[8];
44ac7ddfbfSEd Maste       size_t idx, percent_var_idx;
45435933ddSDimitry Andric       for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
46435933ddSDimitry Andric         if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
47435933ddSDimitry Andric           const int percent_var_len =
48435933ddSDimitry Andric               ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
49435933ddSDimitry Andric           for (idx = 0; (percent_var_idx = new_command.find(
50435933ddSDimitry Andric                              percent_var, idx)) != std::string::npos;) {
51ac7ddfbfSEd Maste             new_command.erase(percent_var_idx, percent_var_len);
52ac7ddfbfSEd Maste             new_command.insert(percent_var_idx, match_str);
53ac7ddfbfSEd Maste             idx += percent_var_idx + match_str.size();
54ac7ddfbfSEd Maste           }
55ac7ddfbfSEd Maste         }
56ac7ddfbfSEd Maste       }
57ac7ddfbfSEd Maste       // Interpret the new command and return this as the result!
58ac7ddfbfSEd Maste       if (m_interpreter.GetExpandRegexAliases())
59ac7ddfbfSEd Maste         result.GetOutputStream().Printf("%s\n", new_command.c_str());
60435933ddSDimitry Andric       // Pass in true for "no context switching".  The command that called us
61*4ba319b5SDimitry Andric       // should have set up the context appropriately, we shouldn't have to
62*4ba319b5SDimitry Andric       // redo that.
63*4ba319b5SDimitry Andric       return m_interpreter.HandleCommand(
64*4ba319b5SDimitry Andric           new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
65ac7ddfbfSEd Maste     }
66ac7ddfbfSEd Maste   }
67ac7ddfbfSEd Maste   result.SetStatus(eReturnStatusFailed);
68435933ddSDimitry Andric   if (!GetSyntax().empty())
69ac7ddfbfSEd Maste     result.AppendError(GetSyntax());
70ac7ddfbfSEd Maste   else
71*4ba319b5SDimitry Andric     result.GetOutputStream() << "Command contents '" << command
72*4ba319b5SDimitry Andric                              << "' failed to match any "
73*4ba319b5SDimitry Andric                                 "regular expression in the '"
74*4ba319b5SDimitry Andric                              << m_cmd_name << "' regex ";
75ac7ddfbfSEd Maste   return false;
76ac7ddfbfSEd Maste }
77ac7ddfbfSEd Maste 
AddRegexCommand(const char * re_cstr,const char * command_cstr)78435933ddSDimitry Andric bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
79435933ddSDimitry Andric                                                 const char *command_cstr) {
80ac7ddfbfSEd Maste   m_entries.resize(m_entries.size() + 1);
81ac7ddfbfSEd Maste   // Only add the regular expression if it compiles
82435933ddSDimitry Andric   if (m_entries.back().regex.Compile(
83435933ddSDimitry Andric           llvm::StringRef::withNullAsEmpty(re_cstr))) {
84ac7ddfbfSEd Maste     m_entries.back().command.assign(command_cstr);
85ac7ddfbfSEd Maste     return true;
86ac7ddfbfSEd Maste   }
87ac7ddfbfSEd Maste   // The regex didn't compile...
88ac7ddfbfSEd Maste   m_entries.pop_back();
89ac7ddfbfSEd Maste   return false;
90ac7ddfbfSEd Maste }
91ac7ddfbfSEd Maste 
HandleCompletion(CompletionRequest & request)92*4ba319b5SDimitry Andric int CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
93435933ddSDimitry Andric   if (m_completion_type_mask) {
94435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
95*4ba319b5SDimitry Andric         GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
96*4ba319b5SDimitry Andric     return request.GetNumberOfMatches();
97435933ddSDimitry Andric   } else {
98*4ba319b5SDimitry Andric     request.SetWordComplete(false);
99ac7ddfbfSEd Maste   }
100ac7ddfbfSEd Maste   return 0;
101ac7ddfbfSEd Maste }
102