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(1): fix .INCLUDEDFROMDIR/.INCLUDEDFROMFILE



details:   https://anonhg.NetBSD.org/src/rev/e11263f9cb49
branches:  trunk
changeset: 954527:e11263f9cb49
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Sep 05 18:18:05 2020 +0000

description:
make(1): fix .INCLUDEDFROMDIR/.INCLUDEDFROMFILE

diffstat:

 usr.bin/make/parse.c                     |  128 ++++++++++++++----------------
 usr.bin/make/unit-tests/include-main.exp |   12 +-
 usr.bin/make/unit-tests/include-main.mk  |   10 +-
 3 files changed, 73 insertions(+), 77 deletions(-)

diffs (259 lines):

diff -r 92222e2a9b41 -r e11263f9cb49 usr.bin/make/parse.c
--- a/usr.bin/make/parse.c      Sat Sep 05 18:13:47 2020 +0000
+++ b/usr.bin/make/parse.c      Sat Sep 05 18:18:05 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parse.c,v 1.280 2020/09/05 15:12:03 rillig Exp $       */
+/*     $NetBSD: parse.c,v 1.281 2020/09/05 18:18:05 rillig Exp $       */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: parse.c,v 1.280 2020/09/05 15:12:03 rillig Exp $";
+static char rcsid[] = "$NetBSD: parse.c,v 1.281 2020/09/05 18:18:05 rillig Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)parse.c    8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: parse.c,v 1.280 2020/09/05 15:12:03 rillig Exp $");
+__RCSID("$NetBSD: parse.c,v 1.281 2020/09/05 18:18:05 rillig Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -150,6 +150,7 @@
  */
 typedef struct IFile {
     char           *fname;         /* name of file */
+    Boolean         fromForLoop;    /* simulated .include by the .for loop */
     int             lineno;         /* current line number in file */
     int             first_lineno;   /* line number of start of text */
     int             cond_depth;     /* 'if' nesting when file opened */
@@ -269,7 +270,7 @@
 
 /* The current file from the command line (at the bottom of the stack) and
  * further up all the files that are currently being read due to nested
- * .include directives. */
+ * .include or .for directives. */
 static Stack /* of *IFile */ includes;
 
 /* include paths (lists of directories) */
@@ -337,10 +338,6 @@
 { ".WAIT",       Wait,         0 },
 };
 
-/* local functions */
-
-static void ParseSetIncludedFile(void);
-
 /* file loader */
 
 struct loadedfile {
@@ -2254,7 +2251,6 @@
     /* load it */
     lf = loadfile(fullname, fd);
 
-    ParseSetIncludedFile();
     /* Start reading from this file next */
     Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
     curFile->lf = lf;
@@ -2313,74 +2309,70 @@
     free(file);
 }
 
+/* Split filename into dirname + basename, then assign these to the
+ * given variables. */
+static void
+SetFilenameVars(const char *filename, const char *dirvar, const char *filevar)
+{
+    const char *slash, *dirname, *basename;
+    void *freeIt;
 
-/*-
- *---------------------------------------------------------------------
- * ParseSetIncludedFile  --
- *     Set the .INCLUDEDFROMFILE variable to the contents of .PARSEFILE
- *     and the .INCLUDEDFROMDIR variable to the contents of .PARSEDIR
- *
- * Results:
- *     None
- *
- * Side Effects:
- *     The .INCLUDEDFROMFILE variable is overwritten by the contents
- *     of .PARSEFILE and the .INCLUDEDFROMDIR variable is overwriten
- *     by the contents of .PARSEDIR
- *---------------------------------------------------------------------
- */
-static void
-ParseSetIncludedFile(void)
-{
-    const char *pf, *pd;
-    char *pf_freeIt, *pd_freeIt;
+    slash = strrchr(filename, '/');
+    if (slash == NULL) {
+       dirname = curdir;
+       basename = filename;
+       freeIt = NULL;
+    } else {
+       dirname = freeIt = bmake_strsedup(filename, slash);
+       basename = slash + 1;
+    }
 
-    pf = Var_Value(".PARSEFILE", VAR_GLOBAL, &pf_freeIt);
-    Var_Set(".INCLUDEDFROMFILE", pf, VAR_GLOBAL);
-    pd = Var_Value(".PARSEDIR", VAR_GLOBAL, &pd_freeIt);
-    Var_Set(".INCLUDEDFROMDIR", pd, VAR_GLOBAL);
+    Var_Set(dirvar, dirname, VAR_GLOBAL);
+    Var_Set(filevar, basename, VAR_GLOBAL);
 
     if (DEBUG(PARSE))
-       fprintf(debug_file, "%s: ${.INCLUDEDFROMDIR} = `%s' "
-           "${.INCLUDEDFROMFILE} = `%s'\n", __func__, pd, pf);
-
-    bmake_free(pf_freeIt);
-    bmake_free(pd_freeIt);
+       fprintf(debug_file, "%s: ${%s} = `%s' ${%s} = `%s'\n",
+               __func__, dirvar, dirname, filevar, basename);
+    free(freeIt);
 }
-/*-
- *---------------------------------------------------------------------
- * ParseSetParseFile  --
- *     Set the .PARSEDIR and .PARSEFILE variables to the dirname and
- *     basename of the given filename
+
+/* Return the immediately including file.
  *
- * Results:
- *     None
- *
- * Side Effects:
- *     The .PARSEDIR and .PARSEFILE variables are overwritten by the
- *     dirname and basename of the given filename.
- *---------------------------------------------------------------------
- */
+ * This is made complicated since the .for loop is implemented as a special
+ * kind of .include; see For_Run. */
+static const char *
+GetActuallyIncludingFile(void)
+{
+    const char *filename = NULL;
+    size_t i;
+
+    /* XXX: Stack was supposed to be an opaque data structure. */
+    for (i = 0; i < includes.len; i++) {
+       IFile *parent = includes.items[i];
+       IFile *child = (i + 1 < includes.len) ? includes.items[i + 1] : curFile;
+       if (!child->fromForLoop)
+           filename = parent->fname;
+    }
+    return filename;
+}
+
+/* Set .PARSEDIR/.PARSEFILE to the given filename, as well as
+ * .INCLUDEDFROMDIR/.INCLUDEDFROMFILE. */
 static void
 ParseSetParseFile(const char *filename)
 {
-    char *slash, *dirname;
-    const char *pd, *pf;
+    const char *including;
+
+    SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE");
 
-    slash = strrchr(filename, '/');
-    if (slash == NULL) {
-       Var_Set(".PARSEDIR", pd = curdir, VAR_GLOBAL);
-       Var_Set(".PARSEFILE", pf = filename, VAR_GLOBAL);
-       dirname = NULL;
+    including = GetActuallyIncludingFile();
+    if (including != NULL) {
+       SetFilenameVars(including,
+                       ".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE");
     } else {
-       dirname = bmake_strsedup(filename, slash);
-       Var_Set(".PARSEDIR", pd = dirname, VAR_GLOBAL);
-       Var_Set(".PARSEFILE", pf = slash + 1, VAR_GLOBAL);
+       Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
+       Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
     }
-    if (DEBUG(PARSE))
-       fprintf(debug_file, "%s: ${.PARSEDIR} = `%s' ${.PARSEFILE} = `%s'\n",
-           __func__, pd, pf);
-    free(dirname);
 }
 
 /*
@@ -2424,8 +2416,9 @@
 {
     char *buf;
     size_t len;
+    Boolean fromForLoop = name == NULL;
 
-    if (name == NULL)
+    if (fromForLoop)
        name = curFile->fname;
     else
        ParseTrackInput(name);
@@ -2439,7 +2432,7 @@
        return;
 
     if (curFile != NULL)
-       /* Save exiting file info */
+       /* Save existing file info */
        Stack_Push(&includes, curFile);
 
     /* Allocate and fill in new structure */
@@ -2452,6 +2445,7 @@
      * place.
      */
     curFile->fname = bmake_strdup(name);
+    curFile->fromForLoop = fromForLoop;
     curFile->lineno = line;
     curFile->first_lineno = line;
     curFile->nextbuf = nextbuf;
diff -r 92222e2a9b41 -r e11263f9cb49 usr.bin/make/unit-tests/include-main.exp
--- a/usr.bin/make/unit-tests/include-main.exp  Sat Sep 05 18:13:47 2020 +0000
+++ b/usr.bin/make/unit-tests/include-main.exp  Sat Sep 05 18:18:05 2020 +0000
@@ -1,10 +1,10 @@
-make: "include-main.mk" line 12: main-before-ok
-make: "include-main.mk" line 19: main-before-for-ok
+make: "include-main.mk" line 14: main-before-ok
+make: "include-main.mk" line 21: main-before-for-ok
 make: "include-sub.mk" line 4: sub-before-ok
 make: "include-sub.mk" line 14: sub-before-for-ok
 make: "include-subsub.mk" line 4: subsub-ok
-make: "include-sub.mk" line 25: warning: sub-after-fail(include-sub.mk)
-make: "include-sub.mk" line 32: warning: sub-after-for-fail(include-sub.mk)
-make: "include-main.mk" line 30: warning: main-after-fail(include-sub.mk)
-make: "include-main.mk" line 35: main-after-for-ok
+make: "include-sub.mk" line 23: sub-after-ok
+make: "include-sub.mk" line 30: sub-after-for-ok
+make: "include-main.mk" line 30: main-after-ok
+make: "include-main.mk" line 37: main-after-for-ok
 exit status 0
diff -r 92222e2a9b41 -r e11263f9cb49 usr.bin/make/unit-tests/include-main.mk
--- a/usr.bin/make/unit-tests/include-main.mk   Sat Sep 05 18:13:47 2020 +0000
+++ b/usr.bin/make/unit-tests/include-main.mk   Sat Sep 05 18:18:05 2020 +0000
@@ -1,12 +1,14 @@
-# $NetBSD: include-main.mk,v 1.4 2020/09/05 18:13:47 rillig Exp $
+# $NetBSD: include-main.mk,v 1.5 2020/09/05 18:18:05 rillig Exp $
 #
-# Demonstrates that the .INCLUDEDFROMFILE magic variable does not behave
+# Until 2020-09-05, the .INCLUDEDFROMFILE magic variable did not behave
 # as described in the manual page.
 #
 # The manual page says that it is the "filename of the file this Makefile
-# was included from", while in reality it is the "filename in which the
-# latest .include happened". See parse.c, function ParseSetIncludeFile.
+# was included from", while before 2020-09-05 it was the "filename in which
+# the latest .include happened". See parse.c, function ParseSetIncludeFile.
 #
+# Since 2020-09-05, the .INCLUDEDFROMDIR and .INCLUDEDFROMFILE variables
+# properly handle nested includes and even .for loops.
 
 .if !defined(.INCLUDEDFROMFILE)
 .  info main-before-ok



Home | Main Index | Thread Index | Old Index