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: allow targets to be used as multiple-incl...



details:   https://anonhg.NetBSD.org/src/rev/01564b7d90c8
branches:  trunk
changeset: 376487:01564b7d90c8
user:      rillig <rillig%NetBSD.org@localhost>
date:      Tue Jun 20 09:25:33 2023 +0000

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

This style is used by FreeBSD, among others.

diffstat:

 usr.bin/make/cond.c                                 |  63 ++++++++++---
 usr.bin/make/make.h                                 |  12 ++-
 usr.bin/make/parse.c                                |  76 +++++++++-------
 usr.bin/make/unit-tests/Makefile                    |   3 +-
 usr.bin/make/unit-tests/directive-include-guard.exp |  26 ++++-
 usr.bin/make/unit-tests/directive-include-guard.mk  |  96 +++++++++++++++++---
 6 files changed, 200 insertions(+), 76 deletions(-)

diffs (truncated from 517 to 300 lines):

diff -r 546b0ae7fd2f -r 01564b7d90c8 usr.bin/make/cond.c
--- a/usr.bin/make/cond.c       Tue Jun 20 08:51:24 2023 +0000
+++ b/usr.bin/make/cond.c       Tue Jun 20 09:25:33 2023 +0000
@@ -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
diff -r 546b0ae7fd2f -r 01564b7d90c8 usr.bin/make/make.h
--- a/usr.bin/make/make.h       Tue Jun 20 08:51:24 2023 +0000
+++ b/usr.bin/make/make.h       Tue Jun 20 09:25:33 2023 +0000
@@ -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 */
diff -r 546b0ae7fd2f -r 01564b7d90c8 usr.bin/make/parse.c
--- a/usr.bin/make/parse.c      Tue Jun 20 08:51:24 2023 +0000
+++ b/usr.bin/make/parse.c      Tue Jun 20 09:25:33 2023 +0000
@@ -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
 }
diff -r 546b0ae7fd2f -r 01564b7d90c8 usr.bin/make/unit-tests/Makefile
--- a/usr.bin/make/unit-tests/Makefile  Tue Jun 20 08:51:24 2023 +0000
+++ b/usr.bin/make/unit-tests/Makefile  Tue Jun 20 09:25:33 2023 +0000
@@ -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)
 #



Home | Main Index | Thread Index | Old Index