JDevlieghere updated this revision to Diff 409963.
JDevlieghere added a comment.

Use Pavel's //not-as-cool// solution.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120101/new/

https://reviews.llvm.org/D120101

Files:
  lldb/source/Commands/CommandObjectRegexCommand.cpp
  lldb/source/Commands/CommandObjectRegexCommand.h
  lldb/unittests/Interpreter/CMakeLists.txt
  lldb/unittests/Interpreter/TestRegexCommand.cpp

Index: lldb/unittests/Interpreter/TestRegexCommand.cpp
===================================================================
--- /dev/null
+++ lldb/unittests/Interpreter/TestRegexCommand.cpp
@@ -0,0 +1,50 @@
+//===-- TestRegexCommand.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Commands/CommandObjectRegexCommand.h"
+
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace {
+class TestRegexCommand : public CommandObjectRegexCommand {
+public:
+  using CommandObjectRegexCommand::SubstituteVariables;
+};
+} // namespace
+
+TEST(RegexCommandTest, SubstituteVariables) {
+  const llvm::SmallVector<llvm::StringRef, 4> substitutions = {"UNUSED", "foo",
+                                                               "bar", "baz"};
+
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%0", substitutions), "%0");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%1", substitutions), "foo");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%2", substitutions), "bar");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%3", substitutions), "baz");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%1%2%3", substitutions),
+            "foobarbaz");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%1%2%3%4", substitutions),
+            "foobarbaz%4");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("#%1#%2#%3#", substitutions),
+            "#foo#bar#baz#");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%11", substitutions), "%11");
+}
+
+TEST(RegexCommandTest, SubstituteVariablesNoRecursion) {
+  const llvm::SmallVector<llvm::StringRef, 4> substitutions = {"UNUSED", "%2",
+                                                               "%3", "%4"};
+
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%0", substitutions), "%0");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%1", substitutions), "%2");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%2", substitutions), "%3");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%3", substitutions), "%4");
+  EXPECT_EQ(TestRegexCommand::SubstituteVariables("%1%2%3", substitutions),
+            "%2%3%4");
+}
Index: lldb/unittests/Interpreter/CMakeLists.txt
===================================================================
--- lldb/unittests/Interpreter/CMakeLists.txt
+++ lldb/unittests/Interpreter/CMakeLists.txt
@@ -4,6 +4,7 @@
   TestOptionArgParser.cpp
   TestOptionValue.cpp
   TestOptionValueFileColonLine.cpp
+  TestRegexCommand.cpp
 
   LINK_LIBS
       lldbCore
Index: lldb/source/Commands/CommandObjectRegexCommand.h
===================================================================
--- lldb/source/Commands/CommandObjectRegexCommand.h
+++ lldb/source/Commands/CommandObjectRegexCommand.h
@@ -39,6 +39,15 @@
 protected:
   bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override;
 
+  /// Substitute variables of the format %1 in the input string.
+  ///
+  /// The replacements vector is expected to be the result of a regex match
+  /// with the first element being the full match. That means that %1 will be
+  /// matched with replacements[1] and not replacements[0].
+  static std::string SubstituteVariables(
+      llvm::StringRef input,
+      const llvm::SmallVectorImpl<llvm::StringRef> &replacements);
+
   struct Entry {
     RegularExpression regex;
     std::string command;
Index: lldb/source/Commands/CommandObjectRegexCommand.cpp
===================================================================
--- lldb/source/Commands/CommandObjectRegexCommand.cpp
+++ lldb/source/Commands/CommandObjectRegexCommand.cpp
@@ -25,28 +25,38 @@
 // Destructor
 CommandObjectRegexCommand::~CommandObjectRegexCommand() = default;
 
+std::string CommandObjectRegexCommand::SubstituteVariables(
+    llvm::StringRef input,
+    const llvm::SmallVectorImpl<llvm::StringRef> &replacements) {
+  std::string buffer;
+  llvm::raw_string_ostream output(buffer);
+
+  llvm::SmallVector<llvm::StringRef, 4> parts;
+  input.split(parts, '%');
+
+  output << parts[0];
+  for (llvm::StringRef part : drop_begin(parts)) {
+    size_t idx = 0;
+    if (part.consumeInteger(10, idx))
+      output << '%';
+    else if (idx > 0 && idx < replacements.size())
+      output << replacements[idx];
+    else
+      output << '%' << idx;
+    output << part;
+  }
+
+  return output.str();
+}
+
 bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
                                           CommandReturnObject &result) {
   EntryCollection::const_iterator pos, end = m_entries.end();
   for (pos = m_entries.begin(); pos != end; ++pos) {
     llvm::SmallVector<llvm::StringRef, 4> matches;
     if (pos->regex.Execute(command, &matches)) {
-      std::string new_command(pos->command);
-      char percent_var[8];
-      size_t idx, percent_var_idx;
-      for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
-        if (match_idx < matches.size()) {
-          const std::string match_str = matches[match_idx].str();
-          const int percent_var_len =
-              ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
-          for (idx = 0; (percent_var_idx = new_command.find(
-                             percent_var, idx)) != std::string::npos;) {
-            new_command.erase(percent_var_idx, percent_var_len);
-            new_command.insert(percent_var_idx, match_str);
-            idx = percent_var_idx + match_str.size();
-          }
-        }
-      }
+      std::string new_command = SubstituteVariables(pos->command, matches);
+
       // Interpret the new command and return this as the result!
       if (m_interpreter.GetExpandRegexAliases())
         result.GetOutputStream().Printf("%s\n", new_command.c_str());
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to