Merge branch 'chipsalliance:master' into fix/2607
diff --git a/verible/verilog/formatting/formatter_test.cc b/verible/verilog/formatting/formatter_test.cc
index aad3e60..f26c999 100644
--- a/verible/verilog/formatting/formatter_test.cc
+++ b/verible/verilog/formatting/formatter_test.cc
@@ -128,6 +128,22 @@
   RunFormatterTestCases40(kSmokeFormatterTestCases);
 }
 
+// Regression for https://github.com/chipsalliance/verible/issues/2607:
+// A CRLF macro definition must keep a single line terminator so formatting
+// converges.
+TEST(FormatterEndToEndTest, DefineCrlfConverges) {
+  static constexpr std::string_view kInput =
+      "`define A x.y\r\n"
+      "module m;\r\n"
+      "endmodule\r\n";
+  FormatStyle style;
+  style.line_terminator = verible::LineTerminatorOptionStyle::kAuto;
+  std::ostringstream stream;
+  const auto status = FormatVerilog(kInput, "<filename>", style, stream);
+  EXPECT_OK(status) << status.message();
+  EXPECT_EQ(stream.str(), kInput);
+}
+
 }  // namespace
 }  // namespace formatter
 }  // namespace verilog
diff --git a/verible/verilog/parser/verilog-lexer_test.cc b/verible/verilog/parser/verilog-lexer_test.cc
index b1f3788..e23b911 100644
--- a/verible/verilog/parser/verilog-lexer_test.cc
+++ b/verible/verilog/parser/verilog-lexer_test.cc
@@ -472,6 +472,12 @@
 static std::initializer_list<LexerTestData> kMacroDefineTests = {
     {{PP_define, "`define"},
      {TK_SPACE, " "},
+     {PP_Identifier, "A"},
+     {TK_SPACE, " "},
+     {PP_define_body, "x.y"},
+     {TK_NEWLINE, "\r\n"}},
+    {{PP_define, "`define"},
+     {TK_SPACE, " "},
      {PP_Identifier, "FOO"},
      {PP_define_body, ""},
      {TK_NEWLINE, "\n"}},
diff --git a/verible/verilog/parser/verilog.lex b/verible/verilog/parser/verilog.lex
index 759fcc2..3afd55e 100644
--- a/verible/verilog/parser/verilog.lex
+++ b/verible/verilog/parser/verilog.lex
@@ -1229,7 +1229,10 @@
     yymore();
   }
   {DiscontinuedLine} {
-    yyless(yyleng-1);  /* return \n to input stream */
+    if (yyleng >= 2 && yytext[yyleng - 2] == '\r')
+      yyless(yyleng - 2);  /* return \r\n to input stream */
+    else
+      yyless(yyleng - 1);  /* return \n to input stream */
     UpdateLocation();
     yy_pop_state();
     /* Return a dummy token so the Location range of the definition (@$) spans