Subject: Re: make: Dir_FindFile still broken
To: Christos Zoulas <christos@zoulas.com>
From: Simon J. Gerraty <sjg@crufty.net>
List: tech-toolchain
Date: 11/24/2002 22:10:42
Ok, here is the patch I've finished up with.

If .CURDIR is reset, then we re-initialize dirSearchPath as well as
dot and cur.  The only time it makes sense to do this is early in
sys.mk (which is when I do it ;-).

Rather than append to ${.PATH} as dirs are added to .PATH, I rebuild
${.PATH} after any .PATH: line - so as to ensure that the effect of
.DOTLAST is accurately reflected.  The idea is that ${.PATH} should
actually show the dirs in the order they will be searched.

The logic used by Dir_SetPATH() follows that of Dir_FindFile()
which is now also consitent in its calls to DirLoopupSubdir().
Ie. if no .DOTLAST, we look in 'dot' and 'cur' first (which is what
DirFindDot() does), and if we do have .DOTLAST we look in 'dot' and
'cur' last.  Also we avoid looking in 'dot' more than once.

--sjg

Index: dir.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/dir.c,v
retrieving revision 1.34
diff -u -p -r1.34 dir.c
--- dir.c	2002/06/15 18:24:56	1.34
+++ dir.c	2002/11/25 06:08:40
@@ -62,6 +62,8 @@ __RCSID("$NetBSD: dir.c,v 1.34 2002/06/1
  *
  *	Dir_End  	    Cleanup the module.
  *
+ *	Dir_SetPATH	    Set ${.PATH} to reflect state of dirSearchPath.
+ *
  *	Dir_HasWildcards    Returns TRUE if the name given it needs to
  *	    	  	    be wildcard-expanded.
  *
@@ -284,6 +286,7 @@ Dir_InitDot(void)
      * to make sure it's not destroyed.
      */
     dot->refCount += 1;
+    Dir_SetPATH();			/* initialize */
 }
 
 /*-
@@ -318,6 +321,55 @@ Dir_End(void)
 #endif
 }
 
+/*
+ * We want ${.PATH} to indicate the order in which we will actually
+ * search, so we rebuild it after any .PATH: target.
+ * This is the simplest way to deal with the effect of .DOTLAST.
+ */
+void
+Dir_SetPATH (void)
+{
+    LstNode       ln;		/* a list element */
+    Path *p;
+    Boolean	  hasLastDot = FALSE;	/* true we should search dot last */
+
+    Var_Delete(".PATH", VAR_GLOBAL);
+    
+    if (Lst_Open (dirSearchPath) == SUCCESS) {
+	if ((ln = Lst_First (dirSearchPath)) != NILLNODE) {
+	    p = (Path *) Lst_Datum (ln);
+	    if (p == dotLast) {
+		hasLastDot = TRUE;
+		Var_Append(".PATH", dotLast->name, VAR_GLOBAL);
+	    }
+	}
+
+	if (!hasLastDot) {
+	    if (dot)
+		Var_Append(".PATH", dot->name, VAR_GLOBAL);
+	    if (cur)
+		Var_Append(".PATH", cur->name, VAR_GLOBAL);
+	}
+
+	while ((ln = Lst_Next (dirSearchPath)) != NILLNODE) {
+	    p = (Path *) Lst_Datum (ln);
+	    if (p == dotLast)
+		continue;
+	    if (p == dot && hasLastDot)
+		continue;
+	    Var_Append(".PATH", p->name, VAR_GLOBAL);
+	}
+
+	if (hasLastDot) {
+	    if (dot)
+		Var_Append(".PATH", dot->name, VAR_GLOBAL);
+	    if (cur)
+		Var_Append(".PATH", cur->name, VAR_GLOBAL);
+	}
+	Lst_Close(dirSearchPath);
+    }
+}
+
 /*-
  *-----------------------------------------------------------------------
  * DirFindName --
@@ -1065,19 +1117,27 @@ Dir_FindFile(char *name, Lst path)
 	if (DEBUG(DIR)) {
 	    printf("failed. Trying subdirectories...");
 	}
-
-	/* XXX - should we look in `dot' subdirs here? */
 
-	if (!hasLastDot && cur && (file = DirLookupSubdir(cur, name)) != NULL)
-	    return file;
+	if (!hasLastDot) {
+		if (dot) {
+			checkedDot = TRUE;
+			if ((file = DirLookupSubdir(dot, name)) != NULL)
+				return file;
+		}
+		if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
+			return file;
+	}
 
 	(void) Lst_Open (path);
 	while ((ln = Lst_Next (path)) != NILLNODE) {
 	    p = (Path *) Lst_Datum (ln);
 	    if (p == dotLast)
 		continue;
-	    if (p == dot)
+	    if (p == dot) {
+		    if (checkedDot)
+			    continue;
 		checkedDot = TRUE;
+	    }
 	    if ((file = DirLookupSubdir(p, name)) != NULL) {
 		Lst_Close (path);
 		return file;
@@ -1085,8 +1145,15 @@ Dir_FindFile(char *name, Lst path)
 	}
 	Lst_Close (path);
 
-	if (hasLastDot && cur && (file = DirLookupSubdir(cur, name)) != NULL)
-	    return file;
+	if (hasLastDot) {
+		if (dot && !checkedDot) {
+			checkedDot = TRUE;
+			if ((file = DirLookupSubdir(dot, name)) != NULL)
+				return file;
+		}
+		if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
+			return file;
+	}
 
 	if (DEBUG(DIR)) {
 	    printf("failed. ");
@@ -1301,7 +1368,7 @@ Dir_MTime(GNode *gn)
 Path *
 Dir_AddDir(Lst path, const char *name)
 {
-    LstNode       ln;	      /* node in case Path structure is found */
+    LstNode       ln = NILLNODE; /* node in case Path structure is found */
     Path	  *p = NULL;  /* pointer to new Path structure */
     DIR     	  *d;	      /* for reading directory */
     struct dirent *dp;	      /* entry in directory */
@@ -1316,7 +1383,8 @@ Dir_AddDir(Lst path, const char *name)
 	}
     }
 
-    ln = Lst_Find (openDirectories, (ClientData)name, DirFindName);
+    if (path)
+	ln = Lst_Find (openDirectories, (ClientData)name, DirFindName);
     if (ln != NILLNODE) {
 	p = (Path *)Lst_Datum (ln);
 	if (Lst_Member(path, (ClientData)p) == NILLNODE) {
Index: dir.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/dir.h,v
retrieving revision 1.7
diff -u -p -r1.7 dir.h
--- dir.h	2002/06/15 18:24:56	1.7
+++ dir.h	2002/11/25 06:08:40
@@ -57,6 +57,7 @@ typedef struct Path {
 void Dir_Init(const char *);
 void Dir_InitDot(void);
 void Dir_End(void);
+void Dir_SetPATH(void);
 Boolean Dir_HasWildcards(char *);
 void Dir_Expand(char *, Lst, Lst);
 char *Dir_FindFile(char *, Lst);
Index: parse.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/make/parse.c,v
retrieving revision 1.84
diff -u -p -r1.84 parse.c
--- parse.c	2002/06/15 18:24:57	1.84
+++ parse.c	2002/11/25 06:08:42
@@ -1154,6 +1154,7 @@ ParseDoDependency(char *line)
 		break;
 	    case ExPath:
 		Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
+		Dir_SetPATH();
 		break;
 #ifdef POSIX
             case Posix:
@@ -1255,6 +1256,8 @@ ParseDoDependency(char *line)
 	if (paths) {
 	    Lst_Destroy(paths, NOFREE);
 	}
+	if (specType == ExPath)
+	    Dir_SetPATH();
     } else {
 	while (*line) {
 	    /*
@@ -1594,6 +1597,15 @@ Parse_DoVar(char *line, GNode *ctxt)
     }
     if (strcmp(line, MAKEOVERRIDES) == 0)
 	Main_ExportMAKEFLAGS(FALSE);	/* re-export MAKEFLAGS */
+    else if (strcmp(line, ".CURDIR") == 0) {
+	/*
+	 * Somone is trying to be way too clever.
+	 * Let's just pretend they know what they are doing...
+	 * and re-initialize dirSearchPath
+	 */
+	Dir_Init(cp);
+	Dir_InitDot();
+    }
 }