Module Name:    src
Committed By:   rillig
Date:           Tue Jun 20 09:25:34 UTC 2023

Modified Files:
        src/usr.bin/make: cond.c make.h parse.c
        src/usr.bin/make/unit-tests: Makefile directive-include-guard.exp
            directive-include-guard.mk

Log Message:
make: allow targets to be used as multiple-inclusion guards

This style is used by FreeBSD, among others.


To generate a diff of this commit:
cvs rdiff -u -r1.349 -r1.350 src/usr.bin/make/cond.c
cvs rdiff -u -r1.322 -r1.323 src/usr.bin/make/make.h
cvs rdiff -u -r1.701 -r1.702 src/usr.bin/make/parse.c
cvs rdiff -u -r1.338 -r1.339 src/usr.bin/make/unit-tests/Makefile
cvs rdiff -u -r1.5 -r1.6 \
    src/usr.bin/make/unit-tests/directive-include-guard.exp
cvs rdiff -u -r1.6 -r1.7 \
    src/usr.bin/make/unit-tests/directive-include-guard.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/cond.c
diff -u src/usr.bin/make/cond.c:1.349 src/usr.bin/make/cond.c:1.350
--- src/usr.bin/make/cond.c:1.349	Mon Jun 19 20:07:35 2023
+++ src/usr.bin/make/cond.c	Tue Jun 20 09:25:33 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: cond.c,v 1.349 2023/06/19 20:07:35 rillig Exp $	*/
+/*	$NetBSD: cond.c,v 1.350 2023/06/20 09:25:33 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -92,7 +92,7 @@
 #include "dir.h"
 
 /*	"@(#)cond.c	8.2 (Berkeley) 1/2/94"	*/
-MAKE_RCSID("$NetBSD: cond.c,v 1.349 2023/06/19 20:07:35 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.350 2023/06/20 09:25:33 rillig Exp $");
 
 /*
  * Conditional expressions conform to this grammar:
@@ -1252,15 +1252,30 @@ ParseVarnameGuard(const char **pp, const
 	return false;
 }
 
-/*
- * Tests whether the line is a conditional that forms a multiple-inclusion
- * guard, and if so, extracts the guard variable name.
- */
-char *
+static bool
+ParseTargetGuard(const char **pp, const char **target)
+{
+	const char *p = *pp;
+
+	if (ch_isalpha(*p) || *p == '_') {
+		while (ch_isalnum(*p) || *p == '_' || *p == '-'
+		    || *p == '<' || *p == '>' || *p == '.' || *p == '/')
+			p++;
+		*target = *pp;
+		*pp = p;
+		return true;
+	}
+	return false;
+}
+
+/* Extracts the multiple-inclusion guard from a conditional, if any. */
+Guard *
 Cond_ExtractGuard(const char *line)
 {
-	const char *p, *varname;
+	const char *p, *name;
 	Substring dir;
+	enum GuardKind kind;
+	Guard *guard;
 
 	p = line + 1;		/* skip the '.' */
 	cpp_skip_hspace(&p);
@@ -1271,14 +1286,32 @@ Cond_ExtractGuard(const char *line)
 	dir.end = p;
 	cpp_skip_hspace(&p);
 
-	if (Substring_Equals(dir, "if"))
-		return skip_string(&p, "!defined(")
-		    && ParseVarnameGuard(&p, &varname) && strcmp(p, ")") == 0
-		    ? bmake_strsedup(varname, p) : NULL;
-	if (Substring_Equals(dir, "ifndef"))
-		return ParseVarnameGuard(&p, &varname) && *p == '\0'
-		    ? bmake_strsedup(varname, p) : NULL;
+	if (Substring_Equals(dir, "if")) {
+		if (skip_string(&p, "!defined(")) {
+			if (ParseVarnameGuard(&p, &name)
+			    && strcmp(p, ")") == 0)
+				goto found_variable;
+		} else if (skip_string(&p, "!target(")) {
+			if (ParseTargetGuard(&p, &name)
+			    && strcmp(p, ")") == 0)
+				goto found_target;
+		}
+	} else if (Substring_Equals(dir, "ifndef")) {
+		if (ParseVarnameGuard(&p, &name) && *p == '\0')
+			goto found_variable;
+	}
 	return NULL;
+
+found_variable:
+	kind = GK_VARIABLE;
+	goto found;
+found_target:
+	kind = GK_TARGET;
+found:
+	guard = bmake_malloc(sizeof(*guard));
+	guard->kind = kind;
+	guard->name = bmake_strsedup(name, p);
+	return guard;
 }
 
 void

Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.322 src/usr.bin/make/make.h:1.323
--- src/usr.bin/make/make.h:1.322	Mon Jun 19 12:53:57 2023
+++ src/usr.bin/make/make.h	Tue Jun 20 09:25:33 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: make.h,v 1.322 2023/06/19 12:53:57 rillig Exp $	*/
+/*	$NetBSD: make.h,v 1.323 2023/06/20 09:25:33 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -539,6 +539,14 @@ typedef enum CondResult {
 	CR_ERROR		/* Unknown directive or parse error */
 } CondResult;
 
+typedef struct {
+	enum GuardKind {
+		GK_VARIABLE,
+		GK_TARGET
+	} kind;
+	char *name;
+} Guard;
+
 /* Names of the variables that are "local" to a specific target. */
 #define TARGET	"@"		/* Target of dependency */
 #define OODATE	"?"		/* All out-of-date sources */
@@ -793,7 +801,7 @@ void Compat_Make(GNode *, GNode *);
 extern unsigned int cond_depth;
 CondResult Cond_EvalCondition(const char *) MAKE_ATTR_USE;
 CondResult Cond_EvalLine(const char *) MAKE_ATTR_USE;
-char *Cond_ExtractGuard(const char *) MAKE_ATTR_USE;
+Guard *Cond_ExtractGuard(const char *) MAKE_ATTR_USE;
 void Cond_EndFile(void);
 
 /* dir.c; see also dir.h */

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.701 src/usr.bin/make/parse.c:1.702
--- src/usr.bin/make/parse.c:1.701	Mon Jun 19 17:30:56 2023
+++ src/usr.bin/make/parse.c	Tue Jun 20 09:25:33 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.701 2023/06/19 17:30:56 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.702 2023/06/20 09:25:33 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -105,7 +105,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.701 2023/06/19 17:30:56 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.702 2023/06/20 09:25:33 rillig Exp $");
 
 /* Detects a multiple-inclusion guard in a makefile. */
 typedef enum {
@@ -136,8 +136,8 @@ typedef struct IncludedFile {
 	char *buf_ptr;		/* next char to be read */
 	char *buf_end;		/* buf_end[-1] == '\n' */
 
-	GuardState guard;
-	char *guardVarname;
+	GuardState guardState;
+	Guard *guard;
 
 	struct ForLoop *forLoop;
 } IncludedFile;
@@ -310,7 +310,7 @@ static const struct {
 
 enum PosixState posix_state = PS_NOT_YET;
 
-static HashTable guards;
+static HashTable /* full file name -> Guard */ guards;
 
 static IncludedFile *
 GetInclude(size_t i)
@@ -1213,13 +1213,19 @@ FindInQuotPath(const char *file)
 static bool
 SkipGuarded(const char *fullname)
 {
-	char *guard = HashTable_FindValue(&guards, fullname);
-	if (guard != NULL && GNode_ValueDirect(SCOPE_GLOBAL, guard) != NULL) {
-		DEBUG2(PARSE, "Skipping '%s' because '%s' is already set\n",
-		    fullname, guard);
-		return true;
-	}
+	Guard *guard = HashTable_FindValue(&guards, fullname);
+	if (guard != NULL && guard->kind == GK_VARIABLE
+	    && GNode_ValueDirect(SCOPE_GLOBAL, guard->name) != NULL)
+		goto skip;
+	if (guard != NULL && guard->kind == GK_TARGET
+	    && Targ_FindNode(guard->name) != NULL)
+		goto skip;
 	return false;
+
+skip:
+	DEBUG2(PARSE, "Skipping '%s' because '%s' is defined\n",
+	    fullname, guard->name);
+	return true;
 }
 
 /*
@@ -2202,8 +2208,8 @@ Parse_PushInput(const char *name, unsign
 	curFile->forBodyReadLines = readLines;
 	curFile->buf = buf;
 	curFile->depending = doing_depend;	/* restore this on EOF */
-	curFile->guard = forLoop == NULL ? GS_START : GS_NO;
-	curFile->guardVarname = NULL;
+	curFile->guardState = forLoop == NULL ? GS_START : GS_NO;
+	curFile->guard = NULL;
 	curFile->forLoop = forLoop;
 
 	if (forLoop != NULL && !For_NextIteration(forLoop, &curFile->buf))
@@ -2346,15 +2352,15 @@ ParseEOF(void)
 
 	Cond_EndFile();
 
-	if (curFile->guard == GS_DONE) {
-		HashTable_Set(&guards,
-		    curFile->name.str, curFile->guardVarname);
-		curFile->guardVarname = NULL;
+	if (curFile->guardState == GS_DONE)
+		HashTable_Set(&guards, curFile->name.str, curFile->guard);
+	else if (curFile->guard != NULL) {
+		free(curFile->guard->name);
+		free(curFile->guard);
 	}
 
 	FStr_Done(&curFile->name);
 	Buf_Done(&curFile->buf);
-	free(curFile->guardVarname);
 	if (curFile->forLoop != NULL)
 		ForLoop_Free(curFile->forLoop);
 	Vector_Pop(&includes);
@@ -2665,22 +2671,22 @@ ReadHighLevelLine(void)
 		if (line == NULL)
 			return NULL;
 
-		if (curFile->guard != GS_NO
-		    && ((curFile->guard == GS_START && line[0] != '.')
-			|| curFile->guard == GS_DONE))
-			curFile->guard = GS_NO;
+		if (curFile->guardState != GS_NO
+		    && ((curFile->guardState == GS_START && line[0] != '.')
+			|| curFile->guardState == GS_DONE))
+			curFile->guardState = GS_NO;
 		if (line[0] != '.')
 			return line;
 
 		condResult = Cond_EvalLine(line);
-		if (curFile->guard == GS_START) {
-			char *varname;
+		if (curFile->guardState == GS_START) {
+			Guard *guard;
 			if (condResult == CR_TRUE
-			    && (varname = Cond_ExtractGuard(line)) != NULL) {
-				curFile->guard = GS_COND;
-				curFile->guardVarname = varname;
+			    && (guard = Cond_ExtractGuard(line)) != NULL) {
+				curFile->guardState = GS_COND;
+				curFile->guard = guard;
 			} else
-				curFile->guard = GS_NO;
+				curFile->guardState = GS_NO;
 		}
 		switch (condResult) {
 		case CR_FALSE:	/* May also mean a syntax error. */
@@ -2842,15 +2848,16 @@ Parse_GuardElse(void)
 {
 	IncludedFile *curFile = CurFile();
 	if (cond_depth == curFile->condMinDepth + 1)
-		curFile->guard = GS_NO;
+		curFile->guardState = GS_NO;
 }
 
 void
 Parse_GuardEndif(void)
 {
 	IncludedFile *curFile = CurFile();
-	if (cond_depth == curFile->condMinDepth && curFile->guard == GS_COND)
-		curFile->guard = GS_DONE;
+	if (cond_depth == curFile->condMinDepth
+	    && curFile->guardState == GS_COND)
+		curFile->guardState = GS_DONE;
 }
 
 static char *
@@ -3061,8 +3068,11 @@ Parse_End(void)
 	assert(includes.len == 0);
 	Vector_Done(&includes);
 	HashIter_Init(&hi, &guards);
-	while (HashIter_Next(&hi) != NULL)
-		free(hi.entry->value);
+	while (HashIter_Next(&hi) != NULL) {
+		Guard *guard = hi.entry->value;
+		free(guard->name);
+		free(guard);
+	}
 	HashTable_Done(&guards);
 #endif
 }

Index: src/usr.bin/make/unit-tests/Makefile
diff -u src/usr.bin/make/unit-tests/Makefile:1.338 src/usr.bin/make/unit-tests/Makefile:1.339
--- src/usr.bin/make/unit-tests/Makefile:1.338	Fri Jun 16 09:25:13 2023
+++ src/usr.bin/make/unit-tests/Makefile	Tue Jun 20 09:25:34 2023
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.338 2023/06/16 09:25:13 rillig Exp $
+# $NetBSD: Makefile,v 1.339 2023/06/20 09:25:34 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -509,6 +509,7 @@ SED_CMDS.directive-include-guard= \
 	-e '/\.MAKEFLAGS/d' \
 	-e '/^Parsing line/d' \
 	-e '/^SetFilenameVars:/d' \
+	-e '/^ParseDependency/d' \
 	-e '/^ParseEOF:/d'
 SED_CMDS.export=	-e '/^[^=_A-Za-z0-9]*=/d'
 SED_CMDS.export-all=	${SED_CMDS.export}

Index: src/usr.bin/make/unit-tests/directive-include-guard.exp
diff -u src/usr.bin/make/unit-tests/directive-include-guard.exp:1.5 src/usr.bin/make/unit-tests/directive-include-guard.exp:1.6
--- src/usr.bin/make/unit-tests/directive-include-guard.exp:1.5	Mon Jun 19 20:07:35 2023
+++ src/usr.bin/make/unit-tests/directive-include-guard.exp	Tue Jun 20 09:25:34 2023
@@ -1,9 +1,9 @@
 Parse_PushInput: file guarded-ifndef.tmp, line 1
-Skipping 'guarded-ifndef.tmp' because 'GUARDED_IFNDEF' is already set
+Skipping 'guarded-ifndef.tmp' because 'GUARDED_IFNDEF' is defined
 Parse_PushInput: file comments.tmp, line 1
-Skipping 'comments.tmp' because 'COMMENTS' is already set
+Skipping 'comments.tmp' because 'COMMENTS' is defined
 Parse_PushInput: file guarded-if.tmp, line 1
-Skipping 'guarded-if.tmp' because 'GUARDED_IF' is already set
+Skipping 'guarded-if.tmp' because 'GUARDED_IF' is defined
 Parse_PushInput: file triple-negation.tmp, line 1
 Parse_PushInput: file triple-negation.tmp, line 1
 Parse_PushInput: file ifdef-negated.tmp, line 1
@@ -19,11 +19,11 @@ Parse_PushInput: file ifndef-indirect.tm
 Parse_PushInput: file if-indirect.tmp, line 1
 Parse_PushInput: file if-indirect.tmp, line 1
 Parse_PushInput: file varassign-indirect.tmp, line 1
-Skipping 'varassign-indirect.tmp' because 'VARASSIGN_INDIRECT' is already set
+Skipping 'varassign-indirect.tmp' because 'VARASSIGN_INDIRECT' is defined
 Parse_PushInput: file late-assignment.tmp, line 1
-Skipping 'late-assignment.tmp' because 'LATE_ASSIGNMENT' is already set
+Skipping 'late-assignment.tmp' because 'LATE_ASSIGNMENT' is defined
 Parse_PushInput: file two-conditions.tmp, line 1
-Skipping 'two-conditions.tmp' because 'TWO_CONDITIONS' is already set
+Skipping 'two-conditions.tmp' because 'TWO_CONDITIONS' is defined
 Parse_PushInput: file already-set.tmp, line 1
 Parse_PushInput: file already-set.tmp, line 1
 Parse_PushInput: file twice.tmp, line 1
@@ -41,5 +41,17 @@ Parse_PushInput: file if-elif.tmp, line 
 Parse_PushInput: file if-else.tmp, line 1
 Parse_PushInput: file if-else.tmp, line 1
 Parse_PushInput: file inner-if-elif-else.tmp, line 1
-Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is already set
+Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is defined
+Parse_PushInput: file target.tmp, line 1
+Skipping 'target.tmp' because '__target.tmp__' is defined
+Parse_PushInput: file target-sys.tmp, line 1
+Skipping 'target-sys.tmp' because '__<target-sys.tmp>__' is defined
+Parse_PushInput: file target-indirect.tmp, line 1
+Parse_PushInput: file target-indirect.tmp, line 1
+Parse_PushInput: file target-unguarded.tmp, line 1
+Parse_PushInput: file target-unguarded.tmp, line 1
+Parse_PushInput: file target-plus.tmp, line 1
+Parse_PushInput: file target-plus.tmp, line 1
+Parse_PushInput: file target-already-set.tmp, line 1
+Parse_PushInput: file target-already-set.tmp, line 1
 exit status 0

Index: src/usr.bin/make/unit-tests/directive-include-guard.mk
diff -u src/usr.bin/make/unit-tests/directive-include-guard.mk:1.6 src/usr.bin/make/unit-tests/directive-include-guard.mk:1.7
--- src/usr.bin/make/unit-tests/directive-include-guard.mk:1.6	Mon Jun 19 20:07:35 2023
+++ src/usr.bin/make/unit-tests/directive-include-guard.mk	Tue Jun 20 09:25:34 2023
@@ -1,17 +1,22 @@
-# $NetBSD: directive-include-guard.mk,v 1.6 2023/06/19 20:07:35 rillig Exp $
+# $NetBSD: directive-include-guard.mk,v 1.7 2023/06/20 09:25:34 rillig Exp $
 #
 # Tests for multiple-inclusion guards in makefiles.
 #
-# A file that is guarded by a multiple-inclusion guard has the following form:
+# A file that is guarded by a multiple-inclusion guard has one of the
+# following forms:
 #
-#	.ifndef GUARD_NAME
-#	...
-#	GUARD_NAME=	# any value, may also be empty
-#	...
+#	.ifndef GUARD_VARIABLE
 #	.endif
 #
-# When such a file is included later and the guard variable is set, including
-# the file has no effect, as all its content is skipped.
+#	.if !defined(GUARD_VARIABLE)
+#	.endif
+#
+#	.if !target(guard-target)
+#	.endif
+#
+# When such a file is included for the second or later time, and the guard
+# variable is set or the guard target defined, including the file has no
+# effect, as all its content is skipped.
 #
 # See also:
 #	https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
@@ -24,7 +29,7 @@ LINES.guarded-ifndef= \
 	'GUARDED_IFNDEF=' \
 	'.endif'
 # expect: Parse_PushInput: file guarded-ifndef.tmp, line 1
-# expect: Skipping 'guarded-ifndef.tmp' because 'GUARDED_IFNDEF' is already set
+# expect: Skipping 'guarded-ifndef.tmp' because 'GUARDED_IFNDEF' is defined
 
 # Comments and empty lines have no influence on the multiple-inclusion guard.
 INCS+=	comments
@@ -37,7 +42,7 @@ LINES.comments= \
 	'.endif' \
 	'\# comment'
 # expect: Parse_PushInput: file comments.tmp, line 1
-# expect: Skipping 'comments.tmp' because 'COMMENTS' is already set
+# expect: Skipping 'comments.tmp' because 'COMMENTS' is defined
 
 # An alternative form uses the 'defined' function.  It is more verbose than
 # the canonical form.  There are other possible forms as well, such as with a
@@ -48,7 +53,7 @@ LINES.guarded-if= \
 	'GUARDED_IF=' \
 	'.endif'
 # expect: Parse_PushInput: file guarded-if.tmp, line 1
-# expect: Skipping 'guarded-if.tmp' because 'GUARDED_IF' is already set
+# expect: Skipping 'guarded-if.tmp' because 'GUARDED_IF' is defined
 
 # Triple negation is so uncommon that it's not recognized.
 INCS+=	triple-negation
@@ -127,7 +132,7 @@ LINES.varassign-indirect= \
 	'$${VARASSIGN_INDIRECT:L}=' \
 	'.endif'
 # expect: Parse_PushInput: file varassign-indirect.tmp, line 1
-# expect: Skipping 'varassign-indirect.tmp' because 'VARASSIGN_INDIRECT' is already set
+# expect: Skipping 'varassign-indirect.tmp' because 'VARASSIGN_INDIRECT' is defined
 
 # The time at which the guard variable is set doesn't matter, as long as it is
 # set when the file is included the next time.
@@ -138,7 +143,7 @@ LINES.late-assignment= \
 	'LATE_ASSIGNMENT=' \
 	'.endif'
 # expect: Parse_PushInput: file late-assignment.tmp, line 1
-# expect: Skipping 'late-assignment.tmp' because 'LATE_ASSIGNMENT' is already set
+# expect: Skipping 'late-assignment.tmp' because 'LATE_ASSIGNMENT' is defined
 
 # The time at which the guard variable is set doesn't matter, as long as it is
 # set when the file is included the next time.
@@ -150,11 +155,10 @@ LINES.two-conditions= \
 	'.  endif' \
 	'.endif'
 # expect: Parse_PushInput: file two-conditions.tmp, line 1
-# expect: Skipping 'two-conditions.tmp' because 'TWO_CONDITIONS' is already set
+# expect: Skipping 'two-conditions.tmp' because 'TWO_CONDITIONS' is defined
 
-# If the guard variable is already set before the file is included for the
-# first time, the file is not considered guarded, as the makefile parser skips
-# all lines in the inactive part between the '.ifndef' and the '.endif'.
+# If the guard variable is defined before the file is included for the first
+# time, the file is not considered guarded.
 INCS+=	already-set
 LINES.already-set= \
 	'.ifndef ALREADY_SET' \
@@ -258,7 +262,63 @@ LINES.inner-if-elif-else = \
 	'.  endif' \
 	'.endif'
 # expect: Parse_PushInput: file inner-if-elif-else.tmp, line 1
-# expect: Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is already set
+# expect: Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is defined
+
+# The guard can not only be a variable, it can also be a target.
+INCS+=	target
+LINES.target= \
+	'.if !target(__target.tmp__)' \
+	'__target.tmp__: .PHONY' \
+	'.endif'
+# expect: Parse_PushInput: file target.tmp, line 1
+# expect: Skipping 'target.tmp' because '__target.tmp__' is defined
+
+# When used for system files, the target name may include '<' and '>'.
+INCS+=	target-sys
+LINES.target-sys= \
+	'.if !target(__<target-sys.tmp>__)' \
+	'__<target-sys.tmp>__: .PHONY' \
+	'.endif'
+# expect: Parse_PushInput: file target-sys.tmp, line 1
+# expect: Skipping 'target-sys.tmp' because '__<target-sys.tmp>__' is defined
+
+# The target name must not include '$' or other special characters.
+INCS+=	target-indirect
+LINES.target-indirect= \
+	'.if !target($${target-indirect.tmp:L})' \
+	'target-indirect.tmp: .PHONY' \
+	'.endif'
+# expect: Parse_PushInput: file target-indirect.tmp, line 1
+# expect: Parse_PushInput: file target-indirect.tmp, line 1
+
+# If the target is not defined when including the file the next time, the file
+# is not guarded.
+INCS+=	target-unguarded
+LINES.target-unguarded= \
+	'.if !target(target-unguarded)' \
+	'.endif'
+# expect: Parse_PushInput: file target-unguarded.tmp, line 1
+# expect: Parse_PushInput: file target-unguarded.tmp, line 1
+
+# The guard condition must consist of only the guard target, nothing else.
+INCS+=	target-plus
+LINES.target-plus= \
+	'.if !target(target-plus) && 1' \
+	'target-plus: .PHONY' \
+	'.endif'
+# expect: Parse_PushInput: file target-plus.tmp, line 1
+# expect: Parse_PushInput: file target-plus.tmp, line 1
+
+# If the guard target is defined before the file is included for the first
+# time, the file is not considered guarded.
+INCS+=	target-already-set
+LINES.target-already-set= \
+	'.if !target(target-already-set)' \
+	'target-already-set: .PHONY' \
+	'.endif'
+target-already-set: .PHONY
+# expect: Parse_PushInput: file target-already-set.tmp, line 1
+# expect: Parse_PushInput: file target-already-set.tmp, line 1
 
 
 # Include each of the files twice.  The directive-include-guard.exp file

Reply via email to