Module Name:    src
Committed By:   rillig
Date:           Sun Oct  4 07:49:45 UTC 2020

Modified Files:
        src/usr.bin/make: parse.c
        src/usr.bin/make/unit-tests: var-op-sunsh.exp var-op-sunsh.mk

Log Message:
make(1): fix parsing of the :sh assignment operator modifier


To generate a diff of this commit:
cvs rdiff -u -r1.348 -r1.349 src/usr.bin/make/parse.c
cvs rdiff -u -r1.1 -r1.2 src/usr.bin/make/unit-tests/var-op-sunsh.exp \
    src/usr.bin/make/unit-tests/var-op-sunsh.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.348 src/usr.bin/make/parse.c:1.349
--- src/usr.bin/make/parse.c:1.348	Sat Oct  3 21:52:50 2020
+++ src/usr.bin/make/parse.c	Sun Oct  4 07:49:45 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.348 2020/10/03 21:52:50 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.349 2020/10/04 07:49:45 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -131,7 +131,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.348 2020/10/03 21:52:50 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.349 2020/10/04 07:49:45 rillig Exp $");
 
 /* types and constants */
 
@@ -1826,12 +1826,14 @@ Parse_DoVar(char *line, GNode *ctxt)
 
 	default:
 #ifdef SUNSHCMD
-	    while (opc > line && *opc != ':')
+	    while (opc > line && *opc == '\0')
 		opc--;
 
-	    if (strncmp(opc, ":sh", 3) == 0) {
+	    if (opc >= line + 2 &&
+		opc[-2] == ':' && opc[-1] == 's' && opc[0] == 'h')
+	    {
 		type = VAR_SHELL;
-		*opc = '\0';
+		opc[-2] = '\0';
 		break;
 	    }
 #endif

Index: src/usr.bin/make/unit-tests/var-op-sunsh.exp
diff -u src/usr.bin/make/unit-tests/var-op-sunsh.exp:1.1 src/usr.bin/make/unit-tests/var-op-sunsh.exp:1.2
--- src/usr.bin/make/unit-tests/var-op-sunsh.exp:1.1	Sun Oct  4 06:53:15 2020
+++ src/usr.bin/make/unit-tests/var-op-sunsh.exp	Sun Oct  4 07:49:45 2020
@@ -1,3 +1 @@
-make: Unclosed variable specification (expecting '}') for "" (value "echo 123") modifier U
-make: Unclosed variable specification (expecting '}') for "" (value " echo\") modifier U
 exit status 0
Index: src/usr.bin/make/unit-tests/var-op-sunsh.mk
diff -u src/usr.bin/make/unit-tests/var-op-sunsh.mk:1.1 src/usr.bin/make/unit-tests/var-op-sunsh.mk:1.2
--- src/usr.bin/make/unit-tests/var-op-sunsh.mk:1.1	Sun Oct  4 06:53:15 2020
+++ src/usr.bin/make/unit-tests/var-op-sunsh.mk	Sun Oct  4 07:49:45 2020
@@ -1,8 +1,8 @@
-# $NetBSD: var-op-sunsh.mk,v 1.1 2020/10/04 06:53:15 rillig Exp $
+# $NetBSD: var-op-sunsh.mk,v 1.2 2020/10/04 07:49:45 rillig Exp $
 #
 # Tests for the :sh= variable assignment operator, which runs its right-hand
 # side through the shell.  It is a seldom-used alternative to the !=
-# assignment operator.
+# assignment operator, adopted from Sun make.
 
 .MAKEFLAGS: -dL			# Enable sane error messages
 
@@ -13,54 +13,63 @@ VAR:sh=		echo colon-sh
 .  error
 .endif
 
-# XXX: As of 2020-10-04, the ':sh' can even be followed by other characters.
-# This is neither documented by NetBSD make nor by Solaris make.
+# It is also possible to have whitespace around the :sh assignment
+# operator modifier.
+VAR :sh =	echo colon-sh-spaced
+.if ${VAR} != "colon-sh-spaced"
+.  error
+.endif
+
+# Until 2020-10-04, the ':sh' could even be followed by other characters.
+# This was neither documented by NetBSD make nor by Solaris make and was
+# an implementation error.
+#
+# Since 2020-10-04, this is a normal variable assignment using the '='
+# assignment operator.
 VAR:shell=	echo colon-shell
-.if ${VAR} != "colon-shell"
+.if ${${:UVAR\:shell}} != "echo colon-shell"
 .  error
 .endif
 
-# XXX: Several colons can syntactically appear in a variable name.
-# Neither of these should be interpreted as the ':sh' assignment operator
-# modifier.
+# Several colons can syntactically appear in a variable name.
+# Until 2020-10-04, the last of them was interpreted as the ':sh'
+# assignment operator.
+#
+# Since 2020-10-04, the colons are part of the variable name.
 VAR:shoe:shore=	echo two-colons
-.if ${VAR${:U\:}shoe} != "two-colons"
+.if ${${:UVAR\:shoe\:shore}} != "echo two-colons"
 .  error
 .endif
 
-#.MAKEFLAGS: -dcpv
-
-# XXX: As of 2020-10-04, the following expression is wrongly marked as
-# a parse error.  This is caused by the ':sh' modifier.
+# Until 2020-10-04, the following expression was wrongly marked as
+# a parse error.  This was because the parser for variable assignments
+# just looked for the previous ":sh", without taking any contextual
+# information into account.
 #
 # There are two different syntactical elements that look exactly the same:
 # The variable modifier ':sh' and the assignment operator modifier ':sh'.
-# Intuitively this variable name contains the variable modifier, but the
-# parser sees it as operator modifier, in Parse_DoVar.
-#
-VAR.${:Uecho 123:sh}=	echo oops
-.if ${VAR.echo 123} != "oops"
+# Intuitively this variable name contains the variable modifier, but until
+# 2020-10-04, the parser regarded it as an assignment operator modifier, in
+# Parse_DoVar.
+VAR.${:Uecho 123:sh}=	ok-123
+.if ${VAR.123} != "ok-123"
 .  error
 .endif
 
-# XXX: Same pattern here. The ':sh' inside the nested expression is taken
-# for the assignment operator, even though it is escaped by a backslash.
-#
-VAR.${:U echo\:shell}=	echo oops
-.if ${VAR.${:U echo\\}} != "oops"
+# Same pattern here. Until 2020-10-04, the ':sh' inside the nested expression
+# was taken for the :sh assignment operator modifier, even though it was
+# escaped by a backslash.
+VAR.${:U echo\:shell}=	ok-shell
+.if ${VAR.${:U echo\:shell}} != "ok-shell"
 .  error
 .endif
 
-# XXX: The word 'shift' is also affected since it starts with ':sh'.
-#
-VAR.key:shift=		echo Shift
-.if ${VAR.key} != "Shift"
+# Until 2020-10-04, the word 'shift' was also affected since it starts with
+# ':sh'.
+VAR.key:shift=		Shift
+.if ${${:UVAR.key\:shift}} != "Shift"
 .  error
 .endif
 
-.MAKEFLAGS: -d0
-
-# XXX: Despite the error messages the exit status is still 0.
-
 all:
 	@:;

Reply via email to