--- version.c.orig	Wed Apr 21 15:17:53 1993
+++ version.c	Thu Apr 22 09:37:27 1993
@@ -1,4 +1,4 @@
-char *version_string = "3.64";
+char *version_string = "3.64 (vpath+)";
 
 /*
   Local variables:
--- file.h.orig	Mon Jan 25 17:45:49 1993
+++ file.h	Thu Apr 22 09:37:27 1993
@@ -26,6 +26,7 @@
     char *name;
     struct dep *deps;
     struct commands *cmds;	/* Commands to execute for this target */
+    char *hname;                /* Hashed filename */
     char *stem;			/* Implicit stem, if an implicit
     				   rule has been used */
     struct dep *also_make;	/* Targets that are made by making this.  */
@@ -70,6 +71,7 @@
     unsigned int intermediate:1;/* Nonzero if this is an intermediate file.  */
     unsigned int dontcare:1;	/* Nonzero if no complaint is to be made if
 				   this target cannot be remade.  */
+    unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name */
   };
 
 /* Number of intermediate files entered.  */
@@ -81,7 +83,7 @@
 
 extern struct file *lookup_file (), *enter_file ();
 extern void remove_intermediates (), snap_deps ();
-extern void rename_file (), file_hash_enter ();
+extern void rehash_file (), file_hash_enter ();
 
 
 extern time_t f_mtime ();
--- file.c.orig	Wed Mar 10 15:24:57 1993
+++ file.c	Thu Apr 22 09:37:27 1993
@@ -72,7 +72,7 @@
   hashval %= FILE_BUCKETS;
 
   for (f = files[hashval]; f != 0; f = f->next)
-    if (streq (f->name, name))
+    if (streq (f->hname, name))
       return f;
   return 0;
 }
@@ -115,7 +115,7 @@
   hashval %= FILE_BUCKETS;
 
   for (f = files[hashval]; f != 0; f = f->next)
-    if (streq (f->name, name))
+    if (streq (f->hname, name))
       break;
 
   if (f != 0 && !f->double_colon)
@@ -123,7 +123,7 @@
 
   new = (struct file *) xmalloc (sizeof (struct file));
   bzero ((char *) new, sizeof (struct file));
-  new->name = name;
+  new->name = new->hname = name;
   new->update_status = -1;
 
   if (f == 0)
@@ -143,16 +143,16 @@
   return new;
 }
 
-/* Rename FILE to NAME.  This is not as simple as resetting
-   the `name' member, since it must be put in a new hash bucket,
+/* Rehash FILE to NAME.  This is not as simple as resetting
+   the `hname' member, since it must be put in a new hash bucket,
    and possibly merged with an existing file called NAME.  */
 
 void
-rename_file (file, name)
+rehash_file (file, name)
      register struct file *file;
      char *name;
 {
-  char *oldname = file->name;
+  char *oldname = file->hname;
   register unsigned int oldhash;
   register char *n;
 
@@ -189,9 +189,13 @@
   /* Look for an existing file under the new name.  */
 
   for (oldfile = files[newbucket]; oldfile != 0; oldfile = oldfile->next)
-    if (streq (oldfile->name, name))
+    if (streq (oldfile->hname, name))
       break;
 
+  /* If the old file is the same as the new file, something's wrong.  */
+  if (oldfile == file)
+    fatal ("File `%s' renamed to itself! (VPATH+ error?)", name);
+
   if (oldhash != 0 && (newbucket != oldbucket || oldfile != 0))
     {
       /* Remove FILE from its hash bucket.  */
@@ -210,7 +214,7 @@
   /* Give FILE its new name.  */
 
   for (f = file; f != 0; f = f->prev)
-    f->name = name;
+    f->hname = name;
 
   if (oldfile == 0)
     {
@@ -294,6 +298,7 @@
       MERGE (is_target);
       MERGE (cmd_target);
       MERGE (phony);
+      MERGE (ignore_vpath);
 #undef MERGE
 
       file->renamed = oldfile;
--- remake.c.orig	Mon Apr 12 16:52:45 1993
+++ remake.c	Thu Apr 22 09:37:28 1993
@@ -531,15 +531,44 @@
 
   if (!must_make)
     {
-      DEBUGPR ("No need to remake target `%s'.\n");
+      if (debug_flag)
+        {
+          print_spaces(depth);
+          printf("No need to remake target `%s'", file->name);
+          if (!streq(file->name, file->hname))
+              printf("; using VPATH name `%s'", file->hname);
+          printf(".\n");
+          fflush(stdout);
+        }
+
       file->command_state = cs_finished;
       file->update_status = 0;
       file->updated = 1;
+
+      /* Since we don't need to remake the file, convert it to use the
+         VPATH filename if we found one.  hfile will be either the
+         local name if no VPATH or the VPATH name if one was found.  */
+
+      while (file)
+        {
+          file->name = file->hname;
+          file = file->prev;
+        }
+
       return 0;
     }
 
-  DEBUGPR ("Must remake target `%s'.\n");
+  if (debug_flag)
+    {
+      print_spaces(depth);
+      printf("Must remake target `%s'", file->name);
+      if (!streq(file->name, file->hname))
+          printf("; ignoring VPATH name `%s'", file->hname);
+      printf(".\n");
+      fflush(stdout);
+    }
 
+  file->ignore_vpath = 1;
   /* Now, take appropriate actions to remake the file.  */
   remake_file (file);
 
@@ -906,7 +935,7 @@
     {
       mtime = name_mtime (file->name);
 
-      if (mtime == (time_t) -1 && search)
+      if (mtime == (time_t) -1 && search && !file->ignore_vpath)
 	{
 	  /* If name_mtime failed, search VPATH.  */
 	  char *name = file->name;
@@ -919,9 +948,9 @@
 		/* vpath_search and library_search store zero in MTIME
 		   if they didn't need to do a stat call for their work.  */
 		file->last_mtime = mtime;
-	      rename_file (file, name);
+	      rehash_file (file, name);
 	      check_renamed (file);
-	      return file_mtime (file);
+	      mtime = name_mtime (name);
 	    }
 	}
     }
--- implicit.c.orig	Wed Mar 10 15:41:03 1993
+++ implicit.c	Thu Apr 22 09:37:28 1993
@@ -142,7 +142,7 @@
   register struct rule *rule;
   register struct dep *dep;
 
-  char *p;
+  char *p, *vp;
 
 #ifndef	NO_ARCHIVES
   if (archive || ar_name (filename))
@@ -380,10 +380,12 @@
 		}
 	      /* This code, given FILENAME = "lib/foo.o", dependency name
 		 "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c".  */
-	      if (vpath_search (&p, (time_t *) 0))
+	      vp = p;
+	      if (vpath_search (&vp, (time_t *) 0))
 		{
-		  DEBUGP2 ("Found dependency as `%s'.%s\n", p, "");
-		  found_files[deps_found++] = p;
+		  DEBUGP2 ("Found dependency `%s' as VPATH `%s'\n", p, vp);
+		  strcpy(vp, p);
+		  found_files[deps_found++] = vp;
 		  continue;
 		}
 
