Allow guard targets to use variables.

I commonly use __${.PARSEDIR:tA}__ where a unique guard
is needed, __${.PARSEDIR}__ is also useful in many cases.

Combination of patch from rillig and mine
This commit is contained in:
sjg 2023-06-21 04:20:20 +00:00
parent 399bc09bd8
commit e06cdfbde9
3 changed files with 54 additions and 29 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cond.c,v 1.350 2023/06/20 09:25:33 rillig Exp $ */
/* $NetBSD: cond.c,v 1.351 2023/06/21 04:20:20 sjg 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.350 2023/06/20 09:25:33 rillig Exp $");
MAKE_RCSID("$NetBSD: cond.c,v 1.351 2023/06/21 04:20:20 sjg Exp $");
/*
* Conditional expressions conform to this grammar:
@ -1252,22 +1252,6 @@ ParseVarnameGuard(const char **pp, const char **varname)
return false;
}
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)
@ -1292,9 +1276,17 @@ Cond_ExtractGuard(const char *line)
&& strcmp(p, ")") == 0)
goto found_variable;
} else if (skip_string(&p, "!target(")) {
if (ParseTargetGuard(&p, &name)
&& strcmp(p, ")") == 0)
goto found_target;
name = p;
free(ParseWord(&p, false));
if (strcmp(p, ")") == 0) {
char *target;
p = name;
target = ParseWord(&p, true);
guard = bmake_malloc(sizeof(*guard));
guard->kind = GK_TARGET;
guard->name = target;
return guard;
}
}
} else if (Substring_Equals(dir, "ifndef")) {
if (ParseVarnameGuard(&p, &name) && *p == '\0')
@ -1304,10 +1296,6 @@ Cond_ExtractGuard(const char *line)
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);

View File

@ -47,7 +47,13 @@ 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
Skipping 'target-indirect.tmp' because 'target-indirect.tmp' is defined
Parse_PushInput: file target-indirect-PARSEFILE.tmp, line 1
Skipping 'target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined
Parse_PushInput: file target-indirect-PARSEFILE2.tmp, line 1
Skipping 'target-indirect-PARSEFILE2.tmp' because '__target-indirect-PARSEFILE2.tmp__' is defined
Parse_PushInput: file target-indirect-PARSEFILE-tA.tmp, line 1
Skipping 'target-indirect-PARSEFILE-tA.tmp' because '__target-indirect-PARSEFILE-tA.tmp__' is defined
Parse_PushInput: file target-unguarded.tmp, line 1
Parse_PushInput: file target-unguarded.tmp, line 1
Parse_PushInput: file target-plus.tmp, line 1

View File

@ -1,4 +1,4 @@
# $NetBSD: directive-include-guard.mk,v 1.7 2023/06/20 09:25:34 rillig Exp $
# $NetBSD: directive-include-guard.mk,v 1.8 2023/06/21 04:20:21 sjg Exp $
#
# Tests for multiple-inclusion guards in makefiles.
#
@ -282,14 +282,45 @@ LINES.target-sys= \
# 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.
# The target name may include variable references - which will be expanded.
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
# expect: Skipping 'target-indirect.tmp' because 'target-indirect.tmp' is defined
# A common form of guard target is __${.PARSEFILE}__.
# This is only useful of course if basename is unique.
INCS+= target-indirect-PARSEFILE
LINES.target-indirect-PARSEFILE= \
'.if !target(__$${.PARSEFILE}__)' \
'__$${.PARSEFILE}__: .NOTMAIN' \
'.endif'
# expect: Parse_PushInput: file target-indirect-PARSEFILE.tmp, line 1
# expect: Skipping 'target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined
# Confirm that two such guards do not conflict
# again, assuming the basenames are unique.
INCS+= target-indirect-PARSEFILE2
LINES.target-indirect-PARSEFILE2= \
'.if !target(__$${.PARSEFILE}__)' \
'__$${.PARSEFILE}__: .NOTMAIN' \
'.endif'
# expect: Parse_PushInput: file target-indirect-PARSEFILE2.tmp, line 1
# expect: Skipping 'target-indirect-PARSEFILE2.tmp' because '__target-indirect-PARSEFILE2.tmp__' is defined
# Another common form of guard target is __${.PARSEFILE:tA}__.
INCS+= target-indirect-PARSEFILE-tA
LINES.target-indirect-PARSEFILE-tA= \
'.if !target(__$${.PARSEFILE:tA}__)' \
'__$${.PARSEFILE:tA}__: .NOTMAIN' \
'.endif'
# expect: Parse_PushInput: file target-indirect-PARSEFILE-tA.tmp, line 1
# expect: Skipping 'target-indirect-PARSEFILE-tA.tmp' because '__target-indirect-PARSEFILE-tA.tmp__' is defined
# The actual target is __${.OBJDIR}/target-indirect-PARSEFILE-tA.tmp__ but
# ${.OBJDIR}/ gets stripped in post processing.
# If the target is not defined when including the file the next time, the file
# is not guarded.