diff --git a/default.c b/default.c
index 3b6f7ae7..93c993e1 100644
--- a/default.c
+++ b/default.c
@@ -131,10 +131,47 @@ static struct pspec default_terminal_rules[] =
 static const char *default_suffix_rules[] =
   {
 #ifdef VMS
+    ".o",
+    "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".obj",
+    "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".s",
+    "$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".S",
+    "$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".c",
+    "$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".cc",
+    "$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".C",
+    "$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".cpp",
+    "$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".f",
+    "$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".m",
+    "$(LINK.m) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".p",
+    "$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".F",
+    "$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".r",
+    "$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".mod",
+    "$(COMPILE.mod) -o $@ -e $@ $^",
+
+    ".def.sym",
+    "$(COMPILE.def) -o $@ $<",
+
+    ".sh",
+    "copy $< >$@",
+
     ".obj.exe",
     "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
     ".mar.exe",
     "$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
+    ".s.o",
+    "$(COMPILE.s) -o $@ $<",
     ".s.exe",
     "$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
     ".c.exe",
@@ -205,6 +242,27 @@ static const char *default_suffix_rules[] =
     ".tex.dvi",
     "$(TEX) $<",
 
+    ".cpp.o",
+    "$(COMPILE.cpp) $(OUTPUT_OPTION) $<",
+    ".f.o",
+    "$(COMPILE.f) $(OUTPUT_OPTION) $<",
+    ".m.o",
+    "$(COMPILE.m) $(OUTPUT_OPTION) $<",
+    ".p.o",
+    "$(COMPILE.p) $(OUTPUT_OPTION) $<",
+    ".r.o",
+    "$(COMPILE.r) $(OUTPUT_OPTION) $<",
+    ".mod.o",
+    "$(COMPILE.mod) -o $@ $<",
+
+    ".c.ln",
+    "$(LINT.c) -C$* $<",
+    ".y.ln",
+    "$(YACC.y) $< \n rename y_tab.c $@",
+
+    ".l.ln",
+    "@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
+
 #else /* ! VMS */
 
     ".o",
@@ -413,19 +471,44 @@ static const char *default_variables[] =
     "LDLIBS", "",
 #endif
 
+    "LINK.o", "$(LD) $(LDFLAGS)",
     "LINK.obj", "$(LD) $(LDFLAGS)",
 #ifndef GCC_IS_NATIVE
     "CXXLINK.obj", "$(CXXLD) $(LDFLAGS)",
     "COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
 #endif
     "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "LINK.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "COMPILE.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
     "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "COMPILE.C", "$(COMPILE.cc)",
+    "COMPILE.cpp", "$(COMPILE.cc)",
+    "LINK.C", "$(LINK.cc)",
+    "LINK.cpp", "$(LINK.cc)",
     "YACC.y", "$(YACC) $(YFLAGS)",
     "LEX.l", "$(LEX) $(LFLAGS)",
+    "YACC.m", "$(YACC) $(YFLAGS)",
+    "LEX.m", "$(LEX) $(LFLAGS) -t",
     "COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)",
+    "COMPILE.f", "$(FC) $(FFLAGS) $(TARGET_ARCH) -c",
+    "LINK.f", "$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c",
+    "LINK.r", "$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
     "COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "COMPILE.def", "$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH)",
+    "COMPILE.mod", "$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)",
+    "COMPILE.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
     "COMPILE.mar", "$(MACRO) $(MACROFLAGS)",
     "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
+    "LINK.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)",
+    "COMPILE.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c",
+    "PREPROCESS.S", "$(CC) -E $(CPPFLAGS)",
+    "PREPROCESS.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F",
+    "PREPROCESS.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F",
     "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
 
     "MV", "rename/new_version",
diff --git a/dir.c b/dir.c
index 7e00b8f7..1fca3ba2 100644
--- a/dir.c
+++ b/dir.c
@@ -142,6 +142,32 @@ downcase (const char *filename)
 
 #ifdef VMS
 
+static char *
+downcase_inplace(char *filename)
+{
+  char *name;
+  name = filename;
+  while (*name != '\0')
+    {
+      *name = tolower ((unsigned char)*name);
+      ++name;
+    }
+  return filename;
+}
+
+#ifndef _USE_STD_STAT
+/* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino
+   when _USE_STD_STAT is used on the compile line.
+
+   Prior to _USE_STD_STAT support, the st_dev is a pointer to thread
+   static memory containing the device of the last filename looked up.
+
+   Todo: find out if the ino_t still needs to be faked on a directory.
+ */
+
+/* Define this if the older VMS_INO_T is needed */
+#define VMS_INO_T 1
+
 static int
 vms_hash (const char *name)
 {
@@ -200,6 +226,10 @@ vmsstat_dir (const char *name, struct stat *st)
 
   return 0;
 }
+
+# define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)
+
+#endif /* _USE_STD_STAT */
 #endif /* VMS */
 
 /* Hash table of directories.  */
@@ -225,7 +255,7 @@ struct directory_contents
 # define FS_NTFS     0x2
 # define FS_UNKNOWN  0x4
 #else
-# ifdef VMS
+# ifdef VMS_INO_T
     ino_t ino[3];
 # else
     ino_t ino;
@@ -246,7 +276,7 @@ directory_contents_hash_1 (const void *key_0)
   ISTRING_HASH_1 (key->path_key, hash);
   hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
 #else
-# ifdef VMS
+# ifdef VMS_INO_T
   hash = (((unsigned int) key->dev << 4)
           ^ ((unsigned int) key->ino[0]
              + (unsigned int) key->ino[1]
@@ -269,7 +299,7 @@ directory_contents_hash_2 (const void *key_0)
   ISTRING_HASH_2 (key->path_key, hash);
   hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
 #else
-# ifdef VMS
+# ifdef VMS_INO_T
   hash = (((unsigned int) key->dev << 4)
           ^ ~((unsigned int) key->ino[0]
               + (unsigned int) key->ino[1]
@@ -308,7 +338,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
   if (result)
     return result;
 #else
-# ifdef VMS
+# ifdef VMS_INO_T
   result = MAKECMP(x->ino[0], y->ino[0]);
   if (result)
     return result;
@@ -419,13 +449,6 @@ find_directory (const char *name)
   struct directory **dir_slot;
   struct directory dir_key;
 
-#ifdef VMS
-  if ((*name == '.') && (*(name+1) == 0))
-    name = "[]";
-  else
-    name = vmsify (name,1);
-#endif
-
   dir_key.name = name;
   dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);
   dir = *dir_slot;
@@ -439,7 +462,12 @@ find_directory (const char *name)
 
       dir = xmalloc (sizeof (struct directory));
 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
-      dir->name = strcache_add_len (downcase (name), p - name);
+      /* Todo: Why is this only needed on VMS? */
+      {
+        char *lname = downcase_inplace (xstrdup (name));
+        dir->name = strcache_add_len (lname, p - name);
+        free (lname);
+      }
 #else
       dir->name = strcache_add_len (name, p - name);
 #endif
@@ -447,9 +475,7 @@ find_directory (const char *name)
       /* The directory is not in the name hash table.
          Find its device and inode numbers, and look it up by them.  */
 
-#ifdef VMS
-      r = vmsstat_dir (name, &st);
-#elif defined(WINDOWS32)
+#if defined(WINDOWS32)
       {
         char tem[MAXPATHLEN], *tstart, *tend;
 
@@ -492,7 +518,7 @@ find_directory (const char *name)
           dc_key.path_key = w32_path = w32ify (name, 1);
           dc_key.ctime = st.st_ctime;
 #else
-# ifdef VMS
+# ifdef VMS_INO_T
           dc_key.ino[0] = st.st_ino[0];
           dc_key.ino[1] = st.st_ino[1];
           dc_key.ino[2] = st.st_ino[2];
@@ -537,7 +563,7 @@ find_directory (const char *name)
               else
                 dc->fs_flags = FS_UNKNOWN;
 #else
-# ifdef VMS
+# ifdef VMS_INO_T
               dc->ino[0] = st.st_ino[0];
               dc->ino[1] = st.st_ino[1];
               dc->ino[2] = st.st_ino[2];
@@ -602,11 +628,6 @@ dir_contents_file_exists_p (struct directory_contents *dir,
   if (filename != 0)
     _fnlwr (filename); /* lower case for FAT drives */
 #endif
-
-#ifdef VMS
-  filename = vmsify (filename,0);
-#endif
-
   if (filename != 0)
     {
       struct dirfile dirfile_key;
@@ -679,7 +700,9 @@ dir_contents_file_exists_p (struct directory_contents *dir,
         }
 
 #if defined(VMS) && defined(HAVE_DIRENT_H)
-      /* In VMS we get file versions too, which have to be stripped off */
+      /* In VMS we get file versions too, which have to be stripped off.
+         Some versions of VMS return versions on Unix files even when
+         the feature option to strip them is set.  */
       {
         char *p = strrchr (d->d_name, ';');
         if (p)
@@ -703,7 +726,8 @@ dir_contents_file_exists_p (struct directory_contents *dir,
         {
           df = xmalloc (sizeof (struct dirfile));
 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
-          df->name = strcache_add_len (downcase (d->d_name), len);
+          /* TODO: Why is this only needed on VMS? */
+          df->name = strcache_add_len (downcase_inplace (d->d_name), len);
 #else
           df->name = strcache_add_len (d->d_name, len);
 #endif
@@ -734,6 +758,15 @@ dir_contents_file_exists_p (struct directory_contents *dir,
 int
 dir_file_exists_p (const char *dirname, const char *filename)
 {
+#ifdef VMS
+  if ((filename != NULL) && (dirname != NULL))
+    {
+      int want_vmsify;
+      want_vmsify = (strpbrk (dirname, ":<[") != NULL);
+      if (want_vmsify)
+        filename = vmsify (filename, 0);
+    }
+#endif
   return dir_contents_file_exists_p (find_directory (dirname)->contents,
                                      filename);
 }
@@ -752,14 +785,24 @@ file_exists_p (const char *name)
     return ar_member_date (name) != (time_t) -1;
 #endif
 
-#ifdef VMS
-  dirend = strrchr (name, ']');
-  if (dirend == 0)
-    dirend = strrchr (name, ':');
-  if (dirend == 0)
-    return dir_file_exists_p ("[]", name);
-#else /* !VMS */
   dirend = strrchr (name, '/');
+#ifdef VMS
+  if (dirend == 0)
+    {
+      dirend = strrchr (name, ']');
+      dirend == NULL ? dirend : dirend++;
+    }
+  if (dirend == 0)
+    {
+      dirend = strrchr (name, '>');
+      dirend == NULL ? dirend : dirend++;
+    }
+  if (dirend == 0)
+    {
+      dirend = strrchr (name, ':');
+      dirend == NULL ? dirend : dirend++;
+    }
+#endif /* VMS */
 #ifdef HAVE_DOS_PATHS
   /* Forward and backslashes might be mixed.  We need the rightmost one.  */
   {
@@ -774,10 +817,9 @@ file_exists_p (const char *name)
   if (dirend == 0)
 #ifndef _AMIGA
     return dir_file_exists_p (".", name);
-#else /* !VMS && !AMIGA */
+#else /* !AMIGA */
     return dir_file_exists_p ("", name);
 #endif /* AMIGA */
-#endif /* VMS */
 
   slash = dirend;
   if (dirend == name)
@@ -796,7 +838,13 @@ file_exists_p (const char *name)
       p[dirend - name] = '\0';
       dirname = p;
     }
-  return dir_file_exists_p (dirname, slash + 1);
+#ifdef VMS
+  if (*slash == '/')
+    slash++;
+#else
+  slash++;
+#endif
+  return dir_file_exists_p (dirname, slash);
 }
 
 /* Mark FILENAME as 'impossible' for 'file_impossible_p'.
@@ -811,16 +859,25 @@ file_impossible (const char *filename)
   struct directory *dir;
   struct dirfile *new;
 
-#ifdef VMS
-  dirend = strrchr (p, ']');
-  if (dirend == 0)
-    dirend = strrchr (p, ':');
-  dirend++;
-  if (dirend == (char *)1)
-    dir = find_directory ("[]");
-#else
   dirend = strrchr (p, '/');
-# ifdef HAVE_DOS_PATHS
+#ifdef VMS
+  if (dirend == NULL)
+    {
+      dirend = strrchr (p, ']');
+      dirend == NULL ? dirend : dirend++;
+    }
+  if (dirend == NULL)
+    {
+      dirend = strrchr (p, '>');
+      dirend == NULL ? dirend : dirend++;
+    }
+  if (dirend == NULL)
+    {
+      dirend = strrchr (p, ':');
+      dirend == NULL ? dirend : dirend++;
+    }
+#endif
+#ifdef HAVE_DOS_PATHS
   /* Forward and backslashes might be mixed.  We need the rightmost one.  */
   {
     const char *bslash = strrchr (p, '\\');
@@ -830,14 +887,13 @@ file_impossible (const char *filename)
     if (!dirend && p[0] && p[1] == ':')
       dirend = p + 1;
   }
-# endif /* HAVE_DOS_PATHS */
+#endif /* HAVE_DOS_PATHS */
   if (dirend == 0)
-# ifdef _AMIGA
+#ifdef _AMIGA
     dir = find_directory ("");
-# else /* !VMS && !AMIGA */
+#else /* !AMIGA */
     dir = find_directory (".");
-# endif /* AMIGA */
-#endif /* VMS */
+#endif /* AMIGA */
   else
     {
       const char *dirname;
@@ -859,7 +915,14 @@ file_impossible (const char *filename)
           dirname = cp;
         }
       dir = find_directory (dirname);
+#ifdef VMS
+      if (*slash == '/')
+        filename = p = slash + 1;
+      else
+        filename = p = slash;
+#else
       filename = p = slash + 1;
+#endif
     }
 
   if (dir->contents == 0)
@@ -878,6 +941,7 @@ file_impossible (const char *filename)
   new = xmalloc (sizeof (struct dirfile));
   new->length = strlen (filename);
 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+  /* todo: Why is this only needed on VMS? */
   new->name = strcache_add_len (downcase (filename), new->length);
 #else
   new->name = strcache_add_len (filename, new->length);
@@ -895,13 +959,22 @@ file_impossible_p (const char *filename)
   struct directory_contents *dir;
   struct dirfile *dirfile;
   struct dirfile dirfile_key;
-
 #ifdef VMS
-  dirend = strrchr (filename, ']');
-  if (dirend == 0)
-    dir = find_directory ("[]")->contents;
-#else
+  int want_vmsify = 0;
+#endif
+
   dirend = strrchr (filename, '/');
+#ifdef VMS
+  if (dirend == NULL)
+    {
+      want_vmsify = (strpbrk (filename, "]>:^") != NULL);
+      dirend = strrchr (filename, ']');
+    }
+  if (dirend == NULL && want_vmsify)
+    dirend = strrchr (filename, '>');
+  if (dirend == NULL && want_vmsify)
+    dirend = strrchr (filename, ':');
+#endif
 #ifdef HAVE_DOS_PATHS
   /* Forward and backslashes might be mixed.  We need the rightmost one.  */
   {
@@ -916,10 +989,9 @@ file_impossible_p (const char *filename)
   if (dirend == 0)
 #ifdef _AMIGA
     dir = find_directory ("")->contents;
-#else /* !VMS && !AMIGA */
+#else /* !AMIGA */
     dir = find_directory (".")->contents;
 #endif /* AMIGA */
-#endif /* VMS */
   else
     {
       const char *dirname;
@@ -941,7 +1013,14 @@ file_impossible_p (const char *filename)
           dirname = cp;
         }
       dir = find_directory (dirname)->contents;
+#ifdef VMS
+      if (*slash == '/')
+        filename = slash + 1;
+      else
+        filename = slash;
+#else
       filename = slash + 1;
+#endif
     }
 
   if (dir == 0 || dir->dirfiles.ht_vec == 0)
@@ -955,7 +1034,8 @@ file_impossible_p (const char *filename)
   filename = downcase (filename);
 #endif
 #ifdef VMS
-  filename = vmsify (filename, 1);
+  if (want_vmsify)
+    filename = vmsify (filename, 1);
 #endif
 
   dirfile_key.name = filename;
@@ -1005,7 +1085,7 @@ print_dir_data_base (void)
               printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
                       dir->name, dir->contents->path_key,dir->contents->mtime);
 #else  /* WINDOWS32 */
-#ifdef VMS
+#ifdef VMS_INO_T
               printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
                       dir->name, dir->contents->dev,
                       dir->contents->ino[0], dir->contents->ino[1],
@@ -1041,7 +1121,7 @@ print_dir_data_base (void)
               printf (_("# %s (key %s, mtime %d): "),
                       dir->name, dir->contents->path_key, dir->contents->mtime);
 #else  /* WINDOWS32 */
-#ifdef VMS
+#ifdef VMS_INO_T
               printf (_("# %s (device %d, inode [%d,%d,%d]): "),
                       dir->name, dir->contents->dev,
                       dir->contents->ino[0], dir->contents->ino[1],
@@ -1179,9 +1259,14 @@ read_dirstream (__ptr_t stream)
  * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
  * regular file; fix that here.
  */
-#if !defined(stat) && !defined(WINDOWS32)
+#if !defined(stat) && !defined(WINDOWS32) || defined(VMS)
 # ifndef VMS
 int stat (const char *path, struct stat *sbuf);
+# else
+    /* We are done with the fake stat.  Go back to the real stat */
+#   ifdef stat
+#     undef stat
+#   endif
 # endif
 # define local_stat stat
 #else
diff --git a/file.c b/file.c
index e1a8e800..fab1d966 100644
--- a/file.c
+++ b/file.c
@@ -75,8 +75,11 @@ lookup_file (const char *name)
 {
   struct file *f;
   struct file file_key;
-#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
+#ifdef VMS
+  int want_vmsify;
+#ifndef WANT_CASE_SENSITIVE_TARGETS
   char *lname;
+#endif
 #endif
 
   assert (*name != '\0');
@@ -85,6 +88,7 @@ lookup_file (const char *name)
      for names read from makefiles.  It is here for names passed
      on the command line.  */
 #ifdef VMS
+   want_vmsify = (strpbrk (name, "]>:^") != NULL);
 # ifndef WANT_CASE_SENSITIVE_TARGETS
   if (*name != '.')
     {
@@ -100,6 +104,8 @@ lookup_file (const char *name)
 
   while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
       name += 2;
+  while (name[0] == '<' && name[1] == '>' && name[2] != '\0')
+      name += 2;
 #endif
   while (name[0] == '.'
 #ifdef HAVE_DOS_PATHS
@@ -120,15 +126,19 @@ lookup_file (const char *name)
     }
 
   if (*name == '\0')
-    /* It was all slashes after a dot.  */
-#if defined(VMS)
-    name = "[]";
-#elif defined(_AMIGA)
-    name = "";
+    {
+      /* It was all slashes after a dot.  */
+#if defined(_AMIGA)
+      name = "";
 #else
-    name = "./";
+      name = "./";
 #endif
-
+#if defined(VMS)
+      /* TODO - This section is probably not needed. */
+      if (want_vmsify)
+        name = "[]";
+#endif
+    }
   file_key.hname = name;
   f = hash_find_item (&files, &file_key);
 #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
diff --git a/implicit.c b/implicit.c
index 8e1d5416..8e17ff21 100644
--- a/implicit.c
+++ b/implicit.c
@@ -266,12 +266,15 @@ pattern_search (struct file *file, int archive,
       /* Set LASTSLASH to point at the last slash in FILENAME
          but not counting any slash at the end.  (foo/bar/ counts as
          bar/ in directory foo/, not empty in directory foo/bar/.)  */
-#ifdef VMS
-      lastslash = strrchr (filename, ']');
-      if (lastslash == 0)
-        lastslash = strrchr (filename, ':');
-#else
       lastslash = strrchr (filename, '/');
+#ifdef VMS
+      if (lastslash == NULL)
+        lastslash = strrchr (filename, ']');
+      if (lastslash == NULL)
+        lastslash = strrchr (filename, '>');
+      if (lastslash == NULL)
+        lastslash = strrchr (filename, ':');
+#endif
 #ifdef HAVE_DOS_PATHS
       /* Handle backslashes (possibly mixed with forward slashes)
          and the case of "d:file".  */
@@ -282,7 +285,6 @@ pattern_search (struct file *file, int archive,
         if (lastslash == 0 && filename[0] && filename[1] == ':')
           lastslash = filename + 1;
       }
-#endif
 #endif
       if (lastslash != 0 && lastslash[1] == '\0')
         lastslash = 0;
@@ -339,10 +341,10 @@ pattern_search (struct file *file, int archive,
           if (lastslash)
             {
 #ifdef VMS
-              check_lastslash = (strchr (target, ']') == 0
-                                 && strchr (target, ':') == 0);
+              check_lastslash = strpbrk (target, "/]>:") == NULL;
 #else
               check_lastslash = strchr (target, '/') == 0;
+#endif
 #ifdef HAVE_DOS_PATHS
               /* Didn't find it yet: check for DOS-type directories.  */
               if (check_lastslash)
@@ -350,7 +352,6 @@ pattern_search (struct file *file, int archive,
                   char *b = strchr (target, '\\');
                   check_lastslash = !(b || (target[0] && target[1] == ':'));
                 }
-#endif
 #endif
             }
           if (check_lastslash)
diff --git a/read.c b/read.c
index 6ff4bcc3..e67d386e 100644
--- a/read.c
+++ b/read.c
@@ -241,7 +241,8 @@ read_all_makefiles (const char **makefiles)
       static const char *default_makefiles[] =
 #ifdef VMS
         /* all lower case since readdir() (the vms version) 'lowercasifies' */
-        { "makefile.vms", "gnumakefile.", "makefile.", 0 };
+        /* TODO: Above is not always true, this needs more work */
+        { "makefile.vms", "gnumakefile", "makefile", 0 };
 #else
 #ifdef _AMIGA
         { "GNUmakefile", "Makefile", "SMakefile", 0 };
@@ -3099,12 +3100,15 @@ parse_file_seq (char **stringp, unsigned int size, int stopmap,
       /* Strip leading "this directory" references.  */
       if (NONE_SET (flags, PARSEFS_NOSTRIP))
 #ifdef VMS
-        /* Skip leading '[]'s.  */
-        while (p - s > 2 && s[0] == '[' && s[1] == ']')
-#else
+        /* Skip leading '[]'s. should only be one set or bug somwhere else */
+        if (p - s > 2 && s[0] == '[' && s[1] == ']')
+            s += 2;
+        /* Skip leading '<>'s. should only be one set or bug somwhere else */
+        if (p - s > 2 && s[0] == '<' && s[1] == '>')
+            s += 2;
+#endif
         /* Skip leading './'s.  */
         while (p - s > 2 && s[0] == '.' && s[1] == '/')
-#endif
           {
             /* Skip "./" and all following slashes.  */
             s += 2;
@@ -3118,9 +3122,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopmap,
       if (s == p)
         {
         /* The name was stripped to empty ("./"). */
-#if defined(VMS)
-          continue;
-#elif defined(_AMIGA)
+#if defined(_AMIGA)
           /* PDS-- This cannot be right!! */
           tp[0] = '\0';
           nlen = 0;
diff --git a/remake.c b/remake.c
index 299a2aaf..0888cfff 100644
--- a/remake.c
+++ b/remake.c
@@ -1325,6 +1325,8 @@ f_mtime (struct file *file, int search)
               || (file->name[0] == '-' && file->name[1] == 'l'
                   && (name = library_search (file->name, &mtime)) != 0))
             {
+              int name_len;
+
               if (mtime != UNKNOWN_MTIME)
                 /* vpath_search and library_search store UNKNOWN_MTIME
                    if they didn't need to do a stat call for their work.  */
@@ -1333,7 +1335,14 @@ f_mtime (struct file *file, int search)
               /* If we found it in VPATH, see if it's in GPATH too; if so,
                  change the name right now; if not, defer until after the
                  dependencies are updated. */
-              if (gpath_search (name, strlen (name) - strlen (file->name) - 1))
+#ifndef VMS
+              name_len = strlen (name) - strlen (file->name) - 1;
+#else
+              name_len = strlen (name) - strlen (file->name);
+              if (name[name_len - 1] == '/')
+                  name_len--;
+#endif
+              if (gpath_search (name, name_len))
                 {
                   rename_file (file, name);
                   check_renamed (file);
diff --git a/vpath.c b/vpath.c
index 1bcba042..49821cab 100644
--- a/vpath.c
+++ b/vpath.c
@@ -387,6 +387,10 @@ selective_vpath_search (struct vpath *path, const char *file,
         {
 #ifndef VMS
           *p++ = '/';
+#else
+          /* VMS: if this is not in VMS format, treat as Unix format */
+          if ((*p != ':') && (*p != ']') && (*p != '>'))
+            *p++ = '/';
 #endif
           memcpy (p, file, name_dplen);
           p += name_dplen;
@@ -405,6 +409,15 @@ selective_vpath_search (struct vpath *path, const char *file,
           memcpy (p + 1, filename, flen + 1);
         }
       else
+#else
+      /* VMS use a slash if no directory terminator present */
+      if (p != name && p[-1] != '/' && p[-1] != ':' &&
+          p[-1] != '>' && p[-1] != ']')
+        {
+          *p = '/';
+          memcpy (p + 1, filename, flen + 1);
+        }
+      else
 #endif
         memcpy (p, filename, flen + 1);
 
@@ -449,17 +462,20 @@ selective_vpath_search (struct vpath *path, const char *file,
              See if it actually exists.  */
 
 #ifdef VMS
-          exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
-#else
-          /* Clobber a null into the name at the last slash.
-             Now NAME is the name of the directory to look in.  */
-          *p = '\0';
-
-          /* We know the directory is in the hash table now because either
-             construct_vpath_list or the code just above put it there.
-             Does the file we seek exist in it?  */
-          exists_in_cache = exists = dir_file_exists_p (name, filename);
+          /* For VMS syntax just use the original vpath */
+          if (*p != '/')
+            exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
+          else
 #endif
+            {
+              /* Clobber a null into the name at the last slash.
+                 Now NAME is the name of the directory to look in.  */
+              *p = '\0';
+              /* We know the directory is in the hash table now because either
+                 construct_vpath_list or the code just above put it there.
+                 Does the file we seek exist in it?  */
+              exists_in_cache = exists = dir_file_exists_p (name, filename);
+            }
         }
 
       if (exists)
@@ -475,6 +491,10 @@ selective_vpath_search (struct vpath *path, const char *file,
 #ifndef VMS
           /* Put the slash back in NAME.  */
           *p = '/';
+#else
+          /* If the slash was removed, put it back */
+          if (*p == 0)
+            *p = '/';
 #endif
 
           if (exists_in_cache)  /* Makefile-mentioned file need not exist.  */