xref: /llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp (revision d7796855b87911b8ae6c726ab5df4949f173dbd2)
19390b346SJonas Devlieghere //===-- CommandObjectRegexCommand.cpp -------------------------------------===//
29390b346SJonas Devlieghere //
39390b346SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49390b346SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
59390b346SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69390b346SJonas Devlieghere //
79390b346SJonas Devlieghere //===----------------------------------------------------------------------===//
89390b346SJonas Devlieghere 
99390b346SJonas Devlieghere #include "CommandObjectRegexCommand.h"
109390b346SJonas Devlieghere #include "lldb/Interpreter/CommandInterpreter.h"
119390b346SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h"
129390b346SJonas Devlieghere 
132a6dbedfSJonas Devlieghere #include "llvm/Support/Errc.h"
142a6dbedfSJonas Devlieghere #include "llvm/Support/Error.h"
152a6dbedfSJonas Devlieghere 
169390b346SJonas Devlieghere using namespace lldb;
179390b346SJonas Devlieghere using namespace lldb_private;
189390b346SJonas Devlieghere 
199390b346SJonas Devlieghere // CommandObjectRegexCommand constructor
209390b346SJonas Devlieghere CommandObjectRegexCommand::CommandObjectRegexCommand(
219390b346SJonas Devlieghere     CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
2282352538SDave Lee     llvm::StringRef syntax, uint32_t completion_type_mask, bool is_removable)
239390b346SJonas Devlieghere     : CommandObjectRaw(interpreter, name, help, syntax),
2482352538SDave Lee       m_completion_type_mask(completion_type_mask),
25abb0ed44SKazu Hirata       m_is_removable(is_removable) {}
269390b346SJonas Devlieghere 
279390b346SJonas Devlieghere // Destructor
28fd2433e1SJonas Devlieghere CommandObjectRegexCommand::~CommandObjectRegexCommand() = default;
299390b346SJonas Devlieghere 
302a6dbedfSJonas Devlieghere llvm::Expected<std::string> CommandObjectRegexCommand::SubstituteVariables(
312a6dbedfSJonas Devlieghere     llvm::StringRef input,
322a6dbedfSJonas Devlieghere     const llvm::SmallVectorImpl<llvm::StringRef> &replacements) {
332a6dbedfSJonas Devlieghere   std::string buffer;
342a6dbedfSJonas Devlieghere   llvm::raw_string_ostream output(buffer);
352a6dbedfSJonas Devlieghere 
362a6dbedfSJonas Devlieghere   llvm::SmallVector<llvm::StringRef, 4> parts;
372a6dbedfSJonas Devlieghere   input.split(parts, '%');
382a6dbedfSJonas Devlieghere 
392a6dbedfSJonas Devlieghere   output << parts[0];
402a6dbedfSJonas Devlieghere   for (llvm::StringRef part : drop_begin(parts)) {
412a6dbedfSJonas Devlieghere     size_t idx = 0;
422a6dbedfSJonas Devlieghere     if (part.consumeInteger(10, idx))
432a6dbedfSJonas Devlieghere       output << '%';
442a6dbedfSJonas Devlieghere     else if (idx < replacements.size())
452a6dbedfSJonas Devlieghere       output << replacements[idx];
462a6dbedfSJonas Devlieghere     else
472a6dbedfSJonas Devlieghere       return llvm::make_error<llvm::StringError>(
482a6dbedfSJonas Devlieghere           llvm::formatv("%{0} is out of range: not enough arguments specified",
492a6dbedfSJonas Devlieghere                         idx),
502a6dbedfSJonas Devlieghere           llvm::errc::invalid_argument);
512a6dbedfSJonas Devlieghere     output << part;
522a6dbedfSJonas Devlieghere   }
532a6dbedfSJonas Devlieghere 
54*d7796855SYoungsuk Kim   return buffer;
552a6dbedfSJonas Devlieghere }
562a6dbedfSJonas Devlieghere 
5792d8a28cSPete Lawrence void CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
589390b346SJonas Devlieghere                                           CommandReturnObject &result) {
599390b346SJonas Devlieghere   EntryCollection::const_iterator pos, end = m_entries.end();
609390b346SJonas Devlieghere   for (pos = m_entries.begin(); pos != end; ++pos) {
619390b346SJonas Devlieghere     llvm::SmallVector<llvm::StringRef, 4> matches;
629390b346SJonas Devlieghere     if (pos->regex.Execute(command, &matches)) {
632a6dbedfSJonas Devlieghere       llvm::Expected<std::string> new_command =
642a6dbedfSJonas Devlieghere           SubstituteVariables(pos->command, matches);
652a6dbedfSJonas Devlieghere       if (!new_command) {
662a6dbedfSJonas Devlieghere         result.SetError(new_command.takeError());
6792d8a28cSPete Lawrence         return;
689390b346SJonas Devlieghere       }
692a6dbedfSJonas Devlieghere 
709390b346SJonas Devlieghere       // Interpret the new command and return this as the result!
719390b346SJonas Devlieghere       if (m_interpreter.GetExpandRegexAliases())
722a6dbedfSJonas Devlieghere         result.GetOutputStream().Printf("%s\n", new_command->c_str());
738cc8b36fSJim Ingham       // We don't have to pass an override_context here, as the command that
748cc8b36fSJim Ingham       // called us should have set up the context appropriately.
755e0ee1b3SDave Lee       bool force_repeat_command = true;
7692d8a28cSPete Lawrence       m_interpreter.HandleCommand(new_command->c_str(), eLazyBoolNo, result,
7792d8a28cSPete Lawrence                                   force_repeat_command);
7892d8a28cSPete Lawrence       return;
799390b346SJonas Devlieghere     }
809390b346SJonas Devlieghere   }
819390b346SJonas Devlieghere   result.SetStatus(eReturnStatusFailed);
829390b346SJonas Devlieghere   if (!GetSyntax().empty())
839390b346SJonas Devlieghere     result.AppendError(GetSyntax());
849390b346SJonas Devlieghere   else
852a6dbedfSJonas Devlieghere     result.GetErrorStream() << "Command contents '" << command
869390b346SJonas Devlieghere                             << "' failed to match any "
879390b346SJonas Devlieghere                                "regular expression in the '"
889390b346SJonas Devlieghere                             << m_cmd_name << "' regex ";
899390b346SJonas Devlieghere }
909390b346SJonas Devlieghere 
919390b346SJonas Devlieghere bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr,
929390b346SJonas Devlieghere                                                 llvm::StringRef command_cstr) {
939390b346SJonas Devlieghere   m_entries.resize(m_entries.size() + 1);
949390b346SJonas Devlieghere   // Only add the regular expression if it compiles
959390b346SJonas Devlieghere   m_entries.back().regex = RegularExpression(re_cstr);
969390b346SJonas Devlieghere   if (m_entries.back().regex.IsValid()) {
979390b346SJonas Devlieghere     m_entries.back().command = command_cstr.str();
989390b346SJonas Devlieghere     return true;
999390b346SJonas Devlieghere   }
1009390b346SJonas Devlieghere   // The regex didn't compile...
1019390b346SJonas Devlieghere   m_entries.pop_back();
1029390b346SJonas Devlieghere   return false;
1039390b346SJonas Devlieghere }
1049390b346SJonas Devlieghere 
1059390b346SJonas Devlieghere void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
1069390b346SJonas Devlieghere   if (m_completion_type_mask) {
1076a9c3e61SMed Ismail Bennani     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1089390b346SJonas Devlieghere         GetCommandInterpreter(), m_completion_type_mask, request, nullptr);
1099390b346SJonas Devlieghere   }
1109390b346SJonas Devlieghere }
111