]> git.ipfire.org Git - thirdparty/make.git/commitdiff
Directly handle $\ line endings
authorPaul Smith <psmith@gnu.org>
Sun, 26 Feb 2023 22:30:15 +0000 (17:30 -0500)
committerPaul Smith <psmith@gnu.org>
Sun, 26 Feb 2023 22:30:15 +0000 (17:30 -0500)
Previously we used the fact that this line ending expanded to "$ "
which would then expand to the empty string.  This has problems if
you enable warnings for undefined variables, so directly implement
this special (but documented) trick in the GNU Make parser.

As a side-effect this also removes all previous whitespace when
in GNU Make mode (not in POSIX mode) just as it would without "$".

* src/misc.c (collapse_continuations): Check for "$\" and remove it.
* tests/scripts/variables/flavors: Add regression tests including
with previous whitespace, and escaped/unescaped "$"

src/misc.c
tests/scripts/variables/flavors
tests/scripts/variables/negative

index c362e87e2f90974b2045625256d9830cefd7d8d0..80fd63ace915746647161ae6c5be8600effc87be 100644 (file)
@@ -131,7 +131,7 @@ collapse_continuations (char *line)
   char *q;
 
   q = strchr(in, '\n');
-  if (q == 0)
+  if (!q)
     return;
 
   do
@@ -162,17 +162,33 @@ collapse_continuations (char *line)
 
       if (i & 1)
         {
-          /* Backslash/newline handling:
-             In traditional GNU Make all trailing whitespace, consecutive
-             backslash/newlines, and any leading non-newline whitespace on the
-             next line is reduced to a single space.
-             In POSIX, each backslash/newline and is replaced by a space.  */
+          unsigned int dollar;
+
+          /* Backslash/newline handling: out points to the final "\".
+             In POSIX, each backslash/newline is replaced by a space.
+             In GNU Make all trailing whitespace, consecutive backslash +
+             newlines, and any leading non-newline whitespace on the next line
+             is reduced to a single space.
+             As a special case, replace "$\" with the empty string.  */
           while (ISBLANK (*in))
             ++in;
-          if (! posix_pedantic)
+
+          {
+            const char *dp = out;
+            while (dp > line && dp[-1] == '$')
+              --dp;
+            dollar = (out - dp) % 2;
+          }
+
+          if (dollar)
+            --out;
+
+          if (!posix_pedantic)
             while (out > line && ISBLANK (out[-1]))
               --out;
-          *out++ = ' ';
+
+          if (!dollar)
+            *out++ = ' ';
         }
       else
         {
index 627672f82bd20f6c2c91a71e1cc5a484eea58ceb..ff375b2b21b2e5890249c3f12004621a77cb335a 100644 (file)
@@ -115,13 +115,15 @@ all: ; @: $(info recur=/$(recur)/ simple=/$(simple)/ recure=/$(recur_empty)/ sim
 # TEST 9: Line continuation
 run_make_test(q!
 recur = $\
-  one$\
-  two$\
+  zero  $\
+  one$$\
+  two$$$\
   three
 simple := $\
-  four$\
-  five$\
-  six
+  four  $\
+  five$$\
+  six$$$\
+  seven
 
 all: d$\
      e$\
@@ -130,19 +132,21 @@ all: d$\
 .PHONY: dep
 dep: ; @: $(info recur=/$(recur)/ simple=/$(simple)/)
 !,
-             '', "recur=/onetwothree/ simple=/fourfivesix/\n");
+             '', "recur=/zeroone\$ two\$three/ simple=/fourfive\$ six\$seven/\n");
 
-# TEST 9: Line continuation
+# TEST 9: Line continuation with POSIX
 run_make_test(q!
 .POSIX:
 recur = $\
-  one$\
-  two$\
+  zero  $\
+  one$$\
+  two$$$\
   three
 simple := $\
-  four$\
-  five$\
-  six
+  four  $\
+  five$$\
+  six$$$\
+  seven
 
 all: d$\
      e$\
@@ -151,7 +155,7 @@ all: d$\
 .PHONY: dep
 dep: ; @: $(info recur=/$(recur)/ simple=/$(simple)/)
 !,
-             '', "recur=/onetwothree/ simple=/fourfivesix/\n");
+             '', "recur=/zero  one\$ two\$three/ simple=/four  five\$ six\$seven/\n");
 
 # Test POSIX :::=
 # This creates a recursive variable, but it expands the RHS first.  Any
index 5cb600a827610558e31aaa7a8ea3f8c8289a446f..a49bbef788ecc7d82b694aa7801d9bd7edae8767 100644 (file)
@@ -2,6 +2,8 @@
 
 $description = "Run some negative tests (things that should fail).";
 
+my $unterm = '*** unterminated variable reference.  Stop.';
+
 # TEST #0
 # Check that non-terminated variable references are detected (and
 # reported using the best filename/lineno info
@@ -12,15 +14,12 @@ y = $x
 
 all: ; @echo $y
 ',
-              '', '#MAKEFILE#:3: *** unterminated variable reference.  Stop.',
+              '', "#MAKEFILE#:3: $unterm",
               512);
 
 # TEST #1
 # Bogus variable value passed on the command line.
-run_make_test(undef,
-              ['x=$(other'],
-              '#MAKEFILE#:4: *** unterminated variable reference.  Stop.',
-              512);
+run_make_test(undef, ['x=$(other'], "#MAKEFILE#:4: $unterm", 512);
 
 # TEST #2
 # Again, but this time while reading the makefile.
@@ -33,28 +32,23 @@ z := $y
 
 all: ; @echo $y
 ',
-              '', '#MAKEFILE#:3: *** unterminated variable reference.  Stop.',
-              512);
+              '', "#MAKEFILE#:3: $unterm", 512);
 
 # TEST #3
 # Bogus variable value passed on the command line.
-run_make_test(undef,
-              ['x=$(other'],
-              '#MAKEFILE#:4: *** unterminated variable reference.  Stop.',
-              512);
+run_make_test(undef, ['x=$(other'], "#MAKEFILE#:4: $unterm", 512);
+
+my $nosep = '*** missing separator.  Stop.';
 
 # Whitespace not allowed in variable names
-run_make_test('x y =', '',
-              '#MAKEFILE#:1: *** missing separator.  Stop.', 512);
+run_make_test('x y =', '', "#MAKEFILE#:1: $nosep", 512);
 
-run_make_test('x y=', '',
-              '#MAKEFILE#:1: *** missing separator.  Stop.', 512);
+run_make_test('x y=', '', "#MAKEFILE#:1: $nosep", 512);
 
 # In theory an empty variable should be ignored, but during parsing it's a
 # real token and so this fails.  I'm not 100% sure if this is right or not.
 
-run_make_test('x $X=', '',
-              '#MAKEFILE#:1: *** missing separator.  Stop.', 512);
+run_make_test('x $X=', '', "#MAKEFILE#:1: $nosep", 512);
 
 
 1;