Module Name:    src
Committed By:   rillig
Date:           Tue Aug 27 04:52:14 UTC 2024

Modified Files:
        src/usr.bin/make: main.c make.h var.c
        src/usr.bin/make/unit-tests: var-recursive.exp var-recursive.mk

Log Message:
make: treat recursive variables non-fatally

A recursive variable is no worse than an unknown modifier, so treat them
in the same way by continuing parsing until the end of the makefile.


To generate a diff of this commit:
cvs rdiff -u -r1.633 -r1.634 src/usr.bin/make/main.c
cvs rdiff -u -r1.345 -r1.346 src/usr.bin/make/make.h
cvs rdiff -u -r1.1137 -r1.1138 src/usr.bin/make/var.c
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/make/unit-tests/var-recursive.exp
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/make/unit-tests/var-recursive.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/main.c
diff -u src/usr.bin/make/main.c:1.633 src/usr.bin/make/main.c:1.634
--- src/usr.bin/make/main.c:1.633	Sun Aug 25 20:44:31 2024
+++ src/usr.bin/make/main.c	Tue Aug 27 04:52:14 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.633 2024/08/25 20:44:31 rillig Exp $	*/
+/*	$NetBSD: main.c,v 1.634 2024/08/27 04:52:14 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -111,7 +111,7 @@
 #include "trace.h"
 
 /*	"@(#)main.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: main.c,v 1.633 2024/08/25 20:44:31 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.634 2024/08/27 04:52:14 rillig Exp $");
 #if defined(MAKE_NATIVE)
 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
 	    "The Regents of the University of California.  "
@@ -1859,13 +1859,6 @@ Error(const char *fmt, ...)
 	main_errors++;
 }
 
-void
-WaitForJobs(void)
-{
-	if (jobsRunning)
-		Job_Wait();
-}
-
 /*
  * Wait for any running jobs to finish, then produce an error message,
  * finally exit immediately.
@@ -1878,7 +1871,8 @@ Fatal(const char *fmt, ...)
 {
 	va_list ap;
 
-	WaitForJobs();
+	if (jobsRunning)
+		Job_Wait();
 
 	(void)fflush(stdout);
 	fprintf(stderr, "%s: ", progname);

Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.345 src/usr.bin/make/make.h:1.346
--- src/usr.bin/make/make.h:1.345	Sun Aug 25 20:44:31 2024
+++ src/usr.bin/make/make.h	Tue Aug 27 04:52:14 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: make.h,v 1.345 2024/08/25 20:44:31 rillig Exp $	*/
+/*	$NetBSD: make.h,v 1.346 2024/08/27 04:52:14 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -864,7 +864,6 @@ char *getTmpdir(void) MAKE_ATTR_USE;
 bool ParseBoolean(const char *, bool) MAKE_ATTR_USE;
 const char *cached_realpath(const char *, char *);
 bool GetBooleanExpr(const char *, bool);
-void WaitForJobs(void);
 
 /* parse.c */
 extern int parseErrors;

Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.1137 src/usr.bin/make/var.c:1.1138
--- src/usr.bin/make/var.c:1.1137	Sun Aug 25 20:44:31 2024
+++ src/usr.bin/make/var.c	Tue Aug 27 04:52:14 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.1137 2024/08/25 20:44:31 rillig Exp $	*/
+/*	$NetBSD: var.c,v 1.1138 2024/08/27 04:52:14 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -129,7 +129,7 @@
 #include "trace.h"
 
 /*	"@(#)var.c	8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1137 2024/08/25 20:44:31 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1138 2024/08/27 04:52:14 rillig Exp $");
 
 /*
  * Variables are defined using one of the VAR=value assignments.  Their
@@ -4573,16 +4573,13 @@ Var_Parse(const char **pp, GNode *scope,
 
 	expr.name = v->name.str;
 	if (v->inUse && VarEvalMode_ShouldEval(emode)) {
-		if (scope->fname != NULL) {
-			fprintf(stderr, "In a command near ");
-			PrintLocation(stderr, false, scope);
-		}
-		WaitForJobs();
 		Parse_Error(PARSE_FATAL, "Variable %s is recursive.",
 		    v->name.str);
-		PrintOnError(NULL, "\n");
-		Trace_Log(MAKEERROR, NULL);
-		exit(2);	/* Not 1 so -q can distinguish error */
+		FStr_Done(&val);
+		if (*p != '\0')
+			p++;
+		*pp = p;
+		return FStr_InitRefer(var_Error);
 	}
 
 	/*

Index: src/usr.bin/make/unit-tests/var-recursive.exp
diff -u src/usr.bin/make/unit-tests/var-recursive.exp:1.10 src/usr.bin/make/unit-tests/var-recursive.exp:1.11
--- src/usr.bin/make/unit-tests/var-recursive.exp:1.10	Sun Aug 25 20:44:31 2024
+++ src/usr.bin/make/unit-tests/var-recursive.exp	Tue Aug 27 04:52:14 2024
@@ -1,23 +1,20 @@
-make: "var-recursive.mk" line 21: still there
-make: "var-recursive.mk" line 23: while evaluating variable "DIRECT" with value "${DIRECT}": Variable DIRECT is recursive.
+make: "var-recursive.mk" line 11: while evaluating variable "DIRECT" with value "${DIRECT}": Variable DIRECT is recursive.
 	in directory <curdir>
-
-make: stopped in unit-tests
-sub-exit status 2
-make: "var-recursive.mk" line 31: while evaluating variable "INDIRECT1" with value "${INDIRECT2}": while evaluating variable "INDIRECT2" with value "${INDIRECT1}": Variable INDIRECT1 is recursive.
+make: "var-recursive.mk" line 11: <>
+make: "var-recursive.mk" line 19: while evaluating variable "INDIRECT1" with value "${INDIRECT2}": while evaluating variable "INDIRECT2" with value "${INDIRECT1}": Variable INDIRECT1 is recursive.
 	in directory <curdir>
-
-make: stopped in unit-tests
-sub-exit status 2
-make: "var-recursive.mk" line 39: ok
-make: "var-recursive.mk" line 48: while evaluating variable "V" with value "$V": Variable V is recursive.
+make: "var-recursive.mk" line 19: <>
+make: "var-recursive.mk" line 26: <ok>
+make: "var-recursive.mk" line 34: while evaluating variable "MODIFIERS" with value "${MODIFIERS:Mpattern}": Variable MODIFIERS is recursive.
 	in directory <curdir>
-
-make: stopped in unit-tests
-sub-exit status 2
+make: "var-recursive.mk" line 34: <Mpattern}>
+make: "var-recursive.mk" line 43: while evaluating variable "V" with value "$V": Variable V is recursive.
+	in directory <curdir>
+make: "var-recursive.mk" line 43: <>
+make: Fatal errors encountered -- cannot continue
+make: stopped making "loadtime" in unit-tests
+sub-exit status 1
 : OK
-In a command near "var-recursive.mk" line 60: make[1]: in target "target": while evaluating variable "VAR" with value "${VAR}": Variable VAR is recursive.
-
-make: stopped making "target" in unit-tests
+make: in target "runtime": while evaluating variable "VAR" with value "${VAR}": Variable VAR is recursive.
 sub-exit status 2
 exit status 0

Index: src/usr.bin/make/unit-tests/var-recursive.mk
diff -u src/usr.bin/make/unit-tests/var-recursive.mk:1.7 src/usr.bin/make/unit-tests/var-recursive.mk:1.8
--- src/usr.bin/make/unit-tests/var-recursive.mk:1.7	Sun Aug 25 20:44:31 2024
+++ src/usr.bin/make/unit-tests/var-recursive.mk	Tue Aug 27 04:52:14 2024
@@ -1,66 +1,64 @@
-# $NetBSD: var-recursive.mk,v 1.7 2024/08/25 20:44:31 rillig Exp $
+# $NetBSD: var-recursive.mk,v 1.8 2024/08/27 04:52:14 rillig Exp $
 #
-# Tests for expressions that refer to themselves and thus
-# cannot be evaluated.
+# Tests for expressions that refer to themselves and thus cannot be
+# evaluated, as that would lead to an endless loop.
 
-TESTS=	direct indirect conditional short target
+.if make(loadtime)
 
-# Since make exits immediately when it detects a recursive expression,
-# the actual tests are run in sub-makes.
-TEST?=	# none
-.if ${TEST} == ""
-all:
-.for test in ${TESTS}
-	@${.MAKE} -f ${MAKEFILE} TEST=${test} || echo "sub-exit status $$?"
-.endfor
-
-.elif ${TEST} == direct
-
-DIRECT=	${DIRECT}	# Defining a recursive variable is not yet an error.
-# expect+1: still there
-.  info still there	# Therefore this line is printed.
-# expect+1: while evaluating variable "DIRECT" with value "${DIRECT}": Variable DIRECT is recursive.
-.  info ${DIRECT}	# But expanding the variable is an error.
+DIRECT=	${DIRECT}	# Defining a recursive variable is not an error.
+# expect+2: while evaluating variable "DIRECT" with value "${DIRECT}": Variable DIRECT is recursive.
+# expect+1: <>
+.  info <${DIRECT}>	# But expanding such a variable is an error.
 
-.elif ${TEST} == indirect
 
 # The chain of variables that refer to each other may be long.
 INDIRECT1=	${INDIRECT2}
 INDIRECT2=	${INDIRECT1}
-# expect+1: while evaluating variable "INDIRECT1" with value "${INDIRECT2}": while evaluating variable "INDIRECT2" with value "${INDIRECT1}": Variable INDIRECT1 is recursive.
-.  info ${INDIRECT1}
+# expect+2: while evaluating variable "INDIRECT1" with value "${INDIRECT2}": while evaluating variable "INDIRECT2" with value "${INDIRECT1}": Variable INDIRECT1 is recursive.
+# expect+1: <>
+.  info <${INDIRECT1}>
 
-.elif ${TEST} == conditional
 
 # The variable refers to itself, but only in the branch of a condition that
-# is never satisfied and is thus not evaluated.
+# is not satisfied and is thus not evaluated.
 CONDITIONAL=	${1:?ok:${CONDITIONAL}}
-# expect+1: ok
-.  info ${CONDITIONAL}
+# expect+1: <ok>
+.  info <${CONDITIONAL}>
+
+
+# An expression with modifiers is skipped halfway.  This can lead to wrong
+# follow-up error messages, but recursive variables occur seldom.
+MODIFIERS=	${MODIFIERS:Mpattern}
+# expect+2: while evaluating variable "MODIFIERS" with value "${MODIFIERS:Mpattern}": Variable MODIFIERS is recursive.
+# expect+1: <Mpattern}>
+.  info <${MODIFIERS}>
 
-.elif ${TEST} == short
 
 # Short variable names can be expanded using the short-hand $V notation,
 # which takes a different code path in Var_Parse for parsing the variable
 # name.  Ensure that these are checked as well.
 V=	$V
-# expect+1: while evaluating variable "V" with value "$V": Variable V is recursive.
-.  info $V
+# expect+2: while evaluating variable "V" with value "$V": Variable V is recursive.
+# expect+1: <>
+.  info <$V>
 
-.elif ${TEST} == target
+.elif make(runtime)
 
 # If a recursive variable is accessed in a command of a target, the makefiles
-# are not parsed anymore, so there is no location information from the
-# .includes and .for directives.  In such a case, use the location of the last
+# have already been fully parsed, so there is no location information from the
+# .include and .for directives.  In such a case, use the location of the last
 # command of the target to provide at least a hint to the location.
 VAR=	${VAR}
-target:
+runtime:
 	: OK
-	: ${VAR}
+# expect: make: in target "runtime": while evaluating variable "VAR" with value "${VAR}": Variable VAR is recursive.
+	: <${VAR}>
 	: OK
 
 .else
-.  error Unknown test "${TEST}"
-.endif
 
 all:
+	@${MAKE} -f ${MAKEFILE} loadtime || echo "sub-exit status $$?"
+	@${MAKE} -f ${MAKEFILE} runtime || echo "sub-exit status $$?"
+
+.endif

Reply via email to