Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make make: if a makefile is protected by a guard, on...
details: https://anonhg.NetBSD.org/src/rev/c235f4878c78
branches: trunk
changeset: 376465:c235f4878c78
user: rillig <rillig%NetBSD.org@localhost>
date: Mon Jun 19 12:53:57 2023 +0000
description:
make: if a makefile is protected by a guard, only include it once
"looks reasonable" sjg@
diffstat:
usr.bin/make/cond.c | 58 +++++++++++++++-
usr.bin/make/make.h | 5 +-
usr.bin/make/parse.c | 76 ++++++++++++++++++++-
usr.bin/make/unit-tests/directive-include-guard.exp | 14 +-
usr.bin/make/unit-tests/directive-include-guard.mk | 62 ++++++++--------
5 files changed, 170 insertions(+), 45 deletions(-)
diffs (truncated from 496 to 300 lines):
diff -r 5b742e3e407a -r c235f4878c78 usr.bin/make/cond.c
--- a/usr.bin/make/cond.c Mon Jun 19 12:33:43 2023 +0000
+++ b/usr.bin/make/cond.c Mon Jun 19 12:53:57 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.346 2023/06/16 07:12:46 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.347 2023/06/19 12:53:57 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.346 2023/06/16 07:12:46 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.347 2023/06/19 12:53:57 rillig Exp $");
/*
* Conditional expressions conform to this grammar:
@@ -1123,6 +1123,7 @@ Cond_EvalLine(const char *line)
/* Return state for previous conditional */
cond_depth--;
+ Parse_GuardEndif();
return cond_states[cond_depth] & IFS_ACTIVE
? CR_TRUE : CR_FALSE;
}
@@ -1150,6 +1151,7 @@ Cond_EvalLine(const char *line)
Parse_Error(PARSE_FATAL, "if-less else");
return CR_TRUE;
}
+ Parse_GuardElse();
state = cond_states[cond_depth];
if (state == IFS_INITIAL) {
@@ -1185,6 +1187,7 @@ Cond_EvalLine(const char *line)
Parse_Error(PARSE_FATAL, "if-less elif");
return CR_TRUE;
}
+ Parse_GuardElse();
state = cond_states[cond_depth];
if (state & IFS_SEEN_ELSE) {
Parse_Error(PARSE_WARNING, "extra elif");
@@ -1234,6 +1237,57 @@ Cond_EvalLine(const char *line)
return res;
}
+static bool
+skip_identifier(const char **pp)
+{
+ const char *p = *pp;
+
+ if (ch_isalpha(*p) || *p == '_') {
+ while (ch_isalnum(*p) || *p == '_')
+ p++;
+ *pp = p;
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Tests whether the line is a conditional that forms a multiple-inclusion
+ * guard, and if so, extracts the guard variable name.
+ */
+char *
+Cond_ExtractGuard(const char *line)
+{
+ const char *p = line, *dir, *varname;
+ size_t dir_len;
+
+ if (!skip_string(&p, "."))
+ return NULL;
+ cpp_skip_hspace(&p);
+
+ dir = p;
+ while (ch_isalpha(*p))
+ p++;
+ dir_len = (size_t)(p - dir);
+ cpp_skip_hspace(&p);
+
+ if (dir_len == 2 && memcmp(dir, "if", 2) == 0) {
+ if (!skip_string(&p, "!defined("))
+ return NULL;
+ varname = p;
+ skip_identifier(&p);
+ if (p > varname && strcmp(p, ")") == 0)
+ return bmake_strsedup(varname, p);
+ }
+ if (dir_len == 6 && memcmp(dir, "ifndef", 6) == 0) {
+ varname = p;
+ skip_identifier(&p);
+ if (p > varname && *p == '\0')
+ return bmake_strsedup(varname, p);
+ }
+ return NULL;
+}
+
void
Cond_EndFile(void)
{
diff -r 5b742e3e407a -r c235f4878c78 usr.bin/make/make.h
--- a/usr.bin/make/make.h Mon Jun 19 12:33:43 2023 +0000
+++ b/usr.bin/make/make.h Mon Jun 19 12:53:57 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.321 2023/06/16 07:12:46 rillig Exp $ */
+/* $NetBSD: make.h,v 1.322 2023/06/19 12:53:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -793,6 +793,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;
void Cond_EndFile(void);
/* dir.c; see also dir.h */
@@ -857,6 +858,8 @@ void Parse_PushInput(const char *, unsig
void Parse_MainName(GNodeList *);
int Parse_NumErrors(void) MAKE_ATTR_USE;
unsigned int CurFile_CondMinDepth(void) MAKE_ATTR_USE;
+void Parse_GuardElse(void);
+void Parse_GuardEndif(void);
/* suff.c */
diff -r 5b742e3e407a -r c235f4878c78 usr.bin/make/parse.c
--- a/usr.bin/make/parse.c Mon Jun 19 12:33:43 2023 +0000
+++ b/usr.bin/make/parse.c Mon Jun 19 12:53:57 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.699 2023/06/01 06:25:34 rillig Exp $ */
+/* $NetBSD: parse.c,v 1.700 2023/06/19 12:53:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -105,7 +105,15 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.699 2023/06/01 06:25:34 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.700 2023/06/19 12:53:57 rillig Exp $");
+
+/* Detects a multiple-inclusion guard in a makefile. */
+typedef enum {
+ GS_START, /* at the beginning of the file */
+ GS_COND, /* after the guard condition */
+ GS_DONE, /* after the closing .endif */
+ GS_NO /* the file is not guarded */
+} GuardState;
/*
* A file being read.
@@ -128,6 +136,9 @@ typedef struct IncludedFile {
char *buf_ptr; /* next char to be read */
char *buf_end; /* buf_end[-1] == '\n' */
+ GuardState guard;
+ char *guardVarname;
+
struct ForLoop *forLoop;
} IncludedFile;
@@ -299,6 +310,8 @@ static const struct {
enum PosixState posix_state = PS_NOT_YET;
+static HashTable guards;
+
static IncludedFile *
GetInclude(size_t i)
{
@@ -1212,6 +1225,7 @@ IncludeFile(const char *file, bool isSys
{
Buffer buf;
char *fullname; /* full pathname of file */
+ char *guardVarname;
int fd;
fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
@@ -1231,6 +1245,14 @@ IncludeFile(const char *file, bool isSys
return;
}
+ guardVarname = HashTable_FindValue(&guards, fullname);
+ if (guardVarname != NULL
+ && GNode_ValueDirect(SCOPE_GLOBAL, guardVarname) != NULL) {
+ DEBUG2(PARSE, "Skipping '%s' because '%s' is already set\n",
+ fullname, guardVarname);
+ return;
+ }
+
if ((fd = open(fullname, O_RDONLY)) == -1) {
if (!silent)
Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
@@ -2174,6 +2196,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->forLoop = forLoop;
if (forLoop != NULL && !For_NextIteration(forLoop, &curFile->buf))
@@ -2316,8 +2340,15 @@ ParseEOF(void)
Cond_EndFile();
+ if (curFile->guard == GS_DONE) {
+ HashTable_Set(&guards,
+ curFile->name.str, curFile->guardVarname);
+ curFile->guardVarname = NULL;
+ }
+
FStr_Done(&curFile->name);
Buf_Done(&curFile->buf);
+ free(curFile->guardVarname);
if (curFile->forLoop != NULL)
ForLoop_Free(curFile->forLoop);
Vector_Pop(&includes);
@@ -2616,8 +2647,10 @@ static char *
ReadHighLevelLine(void)
{
char *line;
+ CondResult condResult;
for (;;) {
+ IncludedFile *curFile = CurFile();
line = ReadLowLevelLine(LK_NONEMPTY);
if (posix_state == PS_MAYBE_NEXT_LINE)
posix_state = PS_NOW_OR_NEVER;
@@ -2626,10 +2659,24 @@ 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 (line[0] != '.')
return line;
- switch (Cond_EvalLine(line)) {
+ condResult = Cond_EvalLine(line);
+ if (curFile->guard == GS_START) {
+ char *varname;
+ if (condResult == CR_TRUE
+ && (varname = Cond_ExtractGuard(line)) != NULL) {
+ curFile->guard = GS_COND;
+ curFile->guardVarname = varname;
+ } else
+ curFile->guard = GS_NO;
+ }
+ switch (condResult) {
case CR_FALSE: /* May also mean a syntax error. */
if (!SkipIrrelevantBranches())
return NULL;
@@ -2784,6 +2831,22 @@ Parse_VarAssign(const char *line, bool f
return true;
}
+void
+Parse_GuardElse(void)
+{
+ IncludedFile *curFile = CurFile();
+ if (cond_depth == curFile->condMinDepth + 1)
+ curFile->guard = GS_NO;
+}
+
+void
+Parse_GuardEndif(void)
+{
+ IncludedFile *curFile = CurFile();
+ if (cond_depth == curFile->condMinDepth && curFile->guard == GS_COND)
+ curFile->guard = GS_DONE;
+}
+
static char *
FindSemicolon(char *p)
{
@@ -2974,6 +3037,7 @@ Parse_Init(void)
sysIncPath = SearchPath_New();
defSysIncPath = SearchPath_New();
Vector_Init(&includes, sizeof(IncludedFile));
+ HashTable_Init(&guards);
}
/* Clean up the parsing module. */
@@ -2981,6 +3045,8 @@ void
Parse_End(void)
{
#ifdef CLEANUP
+ HashIter hi;
+
Lst_DoneCall(&targCmds, free);
assert(targets == NULL);
SearchPath_Free(defSysIncPath);
@@ -2988,6 +3054,10 @@ Parse_End(void)
SearchPath_Free(parseIncPath);
assert(includes.len == 0);
Vector_Done(&includes);
Home |
Main Index |
Thread Index |
Old Index