(font-show-log): Add optional arg N to control the limit of font
[bpt/emacs.git] / src / fileio.c
index 269dd33..d289f42 100644 (file)
@@ -5,10 +5,10 @@
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <limits.h>
@@ -52,14 +50,6 @@ Boston, MA 02110-1301, USA.  */
 #endif
 
 #include <ctype.h>
-
-#ifdef VMS
-#include "vmsdir.h"
-#include <perror.h>
-#include <stddef.h>
-#include <string.h>
-#endif
-
 #include <errno.h>
 
 #ifndef vax11c
@@ -113,22 +103,10 @@ extern int errno;
 #define DRIVE_LETTER(x) (tolower (x))
 #endif
 
-#ifdef VMS
-#include <file.h>
-#include <rmsdef.h>
-#include <fab.h>
-#include <nam.h>
-#endif
-
 #include "systime.h"
 
 #ifdef HPUX
 #include <netio.h>
-#ifndef HPUX8
-#ifndef HPUX9
-#include <errnet.h>
-#endif
-#endif
 #endif
 
 #include "commands.h"
@@ -158,6 +136,9 @@ int auto_saving;
    a new file with the same mode as the original */
 int auto_save_mode_bits;
 
+/* Set by auto_save_1 if an error occurred during the last auto-save. */
+int auto_save_error_occurred;
+
 /* The symbol bound to coding-system-for-read when
    insert-file-contents is called for recovering a file.  This is not
    an actual coding system name, but just an indicator to tell
@@ -204,22 +185,8 @@ Lisp_Object Vwrite_region_annotations_so_far;
 /* File name in which we write a list of all our auto save files.  */
 Lisp_Object Vauto_save_list_file_name;
 
-/* Function to call to read a file name.  */
-Lisp_Object Vread_file_name_function;
-
-/* Current predicate used by read_file_name_internal.  */
-Lisp_Object Vread_file_name_predicate;
-
-/* Nonzero means completion ignores case when reading file name.  */
-int read_file_name_completion_ignore_case;
-
-/* Nonzero means, when reading a filename in the minibuffer,
- start out by inserting the default directory into the minibuffer. */
-int insert_default_directory;
-
-/* On VMS, nonzero means write new files with record format stmlf.
-   Zero means use var format.  */
-int vms_stmlf_recfm;
+/* Whether or not files are auto-saved into themselves.  */
+Lisp_Object Vauto_save_visited_file_name;
 
 /* On NT, specifies the directory separator character, used (eg.) when
    expanding file names.  This can be bound to / or \. */
@@ -230,6 +197,13 @@ Lisp_Object Vdirectory_sep_char;
 int write_region_inhibit_fsync;
 #endif
 
+/* Non-zero means call move-file-to-trash in Fdelete_file or
+   Fdelete_directory.  */
+int delete_by_moving_to_trash;
+
+/* Lisp function for moving files to trash.  */
+Lisp_Object Qmove_file_to_trash;
+
 extern Lisp_Object Vuser_login_name;
 
 #ifdef WINDOWSNT
@@ -414,8 +388,7 @@ DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
        doc: /* Return the directory component in file name FILENAME.
 Return nil if FILENAME does not include a directory.
 Otherwise return a directory name.
-Given a Unix syntax file name, returns a string ending in slash;
-on VMS, perhaps instead a string ending in `:', `]' or `>'.  */)
+Given a Unix syntax file name, returns a string ending in slash.  */)
      (filename)
      Lisp_Object filename;
 {
@@ -443,9 +416,6 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.  */)
   p = beg + SBYTES (filename);
 
   while (p != beg && !IS_DIRECTORY_SEP (p[-1])
-#ifdef VMS
-        && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
-#endif /* VMS */
 #ifdef DOS_NT
         /* only recognise drive specifier at the beginning */
         && !(p[-1] == ':'
@@ -510,9 +480,6 @@ or the entire name if it contains no slash.  */)
   end = p = beg + SBYTES (filename);
 
   while (p != beg && !IS_DIRECTORY_SEP (p[-1])
-#ifdef VMS
-        && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
-#endif /* VMS */
 #ifdef DOS_NT
         /* only recognise drive specifier at beginning */
         && !(p[-1] == ':'
@@ -567,64 +534,6 @@ file_name_as_directory (out, in)
       return out;
     }
 
-#ifdef VMS
-  /* Is it already a directory string? */
-  if (in[size] == ':' || in[size] == ']' || in[size] == '>')
-    return out;
-  /* Is it a VMS directory file name?  If so, hack VMS syntax.  */
-  else if (! index (in, '/')
-          && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
-              || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
-              || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
-                               || ! strncmp (&in[size - 5], ".dir", 4))
-                  && (in[size - 1] == '.' || in[size - 1] == ';')
-                  && in[size] == '1')))
-    {
-      register char *p, *dot;
-      char brack;
-
-      /* x.dir -> [.x]
-        dir:x.dir --> dir:[x]
-        dir:[x]y.dir --> dir:[x.y] */
-      p = in + size;
-      while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
-      if (p != in)
-       {
-         strncpy (out, in, p - in);
-         out[p - in] = '\0';
-         if (*p == ':')
-           {
-             brack = ']';
-             strcat (out, ":[");
-           }
-         else
-           {
-             brack = *p;
-             strcat (out, ".");
-           }
-         p++;
-       }
-      else
-       {
-         brack = ']';
-         strcpy (out, "[.");
-       }
-      dot = index (p, '.');
-      if (dot)
-       {
-         /* blindly remove any extension */
-         size = strlen (out) + (dot - p);
-         strncat (out, p, dot - p);
-       }
-      else
-       {
-         strcat (out, p);
-         size = strlen (out);
-       }
-      out[size++] = brack;
-      out[size] = '\0';
-    }
-#else /* not VMS */
   /* For Unix syntax, Append a slash if necessary */
   if (!IS_DIRECTORY_SEP (out[size]))
     {
@@ -635,7 +544,6 @@ file_name_as_directory (out, in)
 #ifdef DOS_NT
   CORRECT_DIR_SEPS (out);
 #endif
-#endif /* not VMS */
   return out;
 }
 
@@ -646,8 +554,7 @@ This operation exists because a directory is also a file, but its name as
 a directory is different from its name as a file.
 The result can be used as the value of `default-directory'
 or passed as second argument to `expand-file-name'.
-For a Unix-syntax file name, just appends a slash.
-On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.  */)
+For a Unix-syntax file name, just appends a slash.  */)
      (file)
      Lisp_Object file;
 {
@@ -672,9 +579,6 @@ On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.  */)
 \f
 /*
  * Convert from directory name to filename.
- * On VMS:
- *       xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
- *       xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
  * On UNIX, it's simple: just make sure there isn't a terminating /
 
  * Value is nonzero if the string output is different from the input.
@@ -685,130 +589,9 @@ directory_file_name (src, dst)
      char *src, *dst;
 {
   long slen;
-#ifdef VMS
-  long rlen;
-  char * ptr, * rptr;
-  char bracket;
-  struct FAB fab = cc$rms_fab;
-  struct NAM nam = cc$rms_nam;
-  char esa[NAM$C_MAXRSS];
-#endif /* VMS */
 
   slen = strlen (src);
-#ifdef VMS
-  if (! index (src, '/')
-      && (src[slen - 1] == ']'
-         || src[slen - 1] == ':'
-         || src[slen - 1] == '>'))
-    {
-      /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
-      fab.fab$l_fna = src;
-      fab.fab$b_fns = slen;
-      fab.fab$l_nam = &nam;
-      fab.fab$l_fop = FAB$M_NAM;
-
-      nam.nam$l_esa = esa;
-      nam.nam$b_ess = sizeof esa;
-      nam.nam$b_nop |= NAM$M_SYNCHK;
-
-      /* We call SYS$PARSE to handle such things as [--] for us. */
-      if (SYS$PARSE (&fab, 0, 0) == RMS$_NORMAL)
-       {
-         slen = nam.nam$b_esl;
-         if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
-           slen -= 2;
-         esa[slen] = '\0';
-         src = esa;
-       }
-      if (src[slen - 1] != ']' && src[slen - 1] != '>')
-       {
-         /* what about when we have logical_name:???? */
-         if (src[slen - 1] == ':')
-           {                   /* Xlate logical name and see what we get */
-             ptr = strcpy (dst, src); /* upper case for getenv */
-             while (*ptr)
-               {
-                 if ('a' <= *ptr && *ptr <= 'z')
-                   *ptr -= 040;
-                 ptr++;
-               }
-             dst[slen - 1] = 0;        /* remove colon */
-             if (!(src = egetenv (dst)))
-               return 0;
-             /* should we jump to the beginning of this procedure?
-                Good points: allows us to use logical names that xlate
-                to Unix names,
-                Bad points: can be a problem if we just translated to a device
-                name...
-                For now, I'll punt and always expect VMS names, and hope for
-                the best! */
-             slen = strlen (src);
-             if (src[slen - 1] != ']' && src[slen - 1] != '>')
-               { /* no recursion here! */
-                 strcpy (dst, src);
-                 return 0;
-               }
-           }
-         else
-           {           /* not a directory spec */
-             strcpy (dst, src);
-             return 0;
-           }
-       }
-      bracket = src[slen - 1];
-
-      /* If bracket is ']' or '>', bracket - 2 is the corresponding
-        opening bracket.  */
-      ptr = index (src, bracket - 2);
-      if (ptr == 0)
-       { /* no opening bracket */
-         strcpy (dst, src);
-         return 0;
-       }
-      if (!(rptr = rindex (src, '.')))
-       rptr = ptr;
-      slen = rptr - src;
-      strncpy (dst, src, slen);
-      dst[slen] = '\0';
-      if (*rptr == '.')
-       {
-         dst[slen++] = bracket;
-         dst[slen] = '\0';
-       }
-      else
-       {
-         /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
-            then translate the device and recurse. */
-         if (dst[slen - 1] == ':'
-             && dst[slen - 2] != ':'   /* skip decnet nodes */
-             && strcmp (src + slen, "[000000]") == 0)
-           {
-             dst[slen - 1] = '\0';
-             if ((ptr = egetenv (dst))
-                 && (rlen = strlen (ptr) - 1) > 0
-                 && (ptr[rlen] == ']' || ptr[rlen] == '>')
-                 && ptr[rlen - 1] == '.')
-               {
-                 char * buf = (char *) alloca (strlen (ptr) + 1);
-                 strcpy (buf, ptr);
-                 buf[rlen - 1] = ']';
-                 buf[rlen] = '\0';
-                 return directory_file_name (buf, dst);
-               }
-             else
-               dst[slen - 1] = ':';
-           }
-         strcat (dst, "[000000]");
-         slen += 8;
-       }
-      rptr++;
-      rlen = strlen (rptr) - 1;
-      strncat (dst, rptr, rlen);
-      dst[slen + rlen] = '\0';
-      strcat (dst, ".DIR.1");
-      return 1;
-    }
-#endif /* VMS */
+
   /* Process as Unix format: just remove any final slash.
      But leave "/" unchanged; do not change it to "".  */
   strcpy (dst, src);
@@ -831,9 +614,7 @@ DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
 This is the name of the file that holds the data for the directory DIRECTORY.
 This operation exists because a directory is also a file, but its name as
 a directory is different from its name as a file.
-In Unix-syntax, this function just removes the final slash.
-On VMS, given a VMS-syntax directory name such as \"[X.Y]\",
-it returns a file name such as \"[X]Y.DIR.1\".  */)
+In Unix-syntax, this function just removes the final slash.  */)
      (directory)
      Lisp_Object directory;
 {
@@ -851,14 +632,7 @@ it returns a file name such as \"[X]Y.DIR.1\".  */)
   if (!NILP (handler))
     return call2 (handler, Qdirectory_file_name, directory);
 
-#ifdef VMS
-  /* 20 extra chars is insufficient for VMS, since we might perform a
-     logical name translation. an equivalence string can be up to 255
-     chars long, so grab that much extra space...  - sss */
-  buf = (char *) alloca (SBYTES (directory) + 20 + 255);
-#else
   buf = (char *) alloca (SBYTES (directory) + 20);
-#endif
   directory_file_name (SDATA (directory), buf);
   return make_specified_string (buf, -1, strlen (buf),
                                STRING_MULTIBYTE (directory));
@@ -1039,20 +813,15 @@ See also the function `substitute-in-file-name'.  */)
      (name, default_directory)
      Lisp_Object name, default_directory;
 {
-  unsigned char *nm;
+  /* These point to SDATA and need to be careful with string-relocation
+     during GC (via DECODE_FILE).  */
+  unsigned char *nm, *newdir;
+  int nm_in_name;
+  /* This should only point to alloca'd data.  */
+  unsigned char *target;
 
-  register unsigned char *newdir, *p, *o;
   int tlen;
-  unsigned char *target;
   struct passwd *pw;
-#ifdef VMS
-  unsigned char * colon = 0;
-  unsigned char * close = 0;
-  unsigned char * slash = 0;
-  unsigned char * brack = 0;
-  int lbrack = 0, rbrack = 0;
-  int dots = 0;
-#endif /* VMS */
 #ifdef DOS_NT
   int drive = 0;
   int collapse_newdir = 1;
@@ -1061,6 +830,7 @@ See also the function `substitute-in-file-name'.  */)
   int length;
   Lisp_Object handler, result;
   int multibyte;
+  Lisp_Object hdir;
 
   CHECK_STRING (name);
 
@@ -1099,43 +869,45 @@ See also the function `substitute-in-file-name'.  */)
        return call3 (handler, Qexpand_file_name, name, default_directory);
     }
 
-  o = SDATA (default_directory);
-
-  /* Make sure DEFAULT_DIRECTORY is properly expanded.
-     It would be better to do this down below where we actually use
-     default_directory.  Unfortunately, calling Fexpand_file_name recursively
-     could invoke GC, and the strings might be relocated.  This would
-     be annoying because we have pointers into strings lying around
-     that would need adjusting, and people would add new pointers to
-     the code and forget to adjust them, resulting in intermittent bugs.
-     Putting this call here avoids all that crud.
-
-     The EQ test avoids infinite recursion.  */
-  if (! NILP (default_directory) && !EQ (default_directory, name)
-      /* Save time in some common cases - as long as default_directory
-        is not relative, it can be canonicalized with name below (if it
-        is needed at all) without requiring it to be expanded now.  */
+  {
+    unsigned char *o = SDATA (default_directory);
+
+    /* Make sure DEFAULT_DIRECTORY is properly expanded.
+       It would be better to do this down below where we actually use
+       default_directory.  Unfortunately, calling Fexpand_file_name recursively
+       could invoke GC, and the strings might be relocated.  This would
+       be annoying because we have pointers into strings lying around
+       that would need adjusting, and people would add new pointers to
+       the code and forget to adjust them, resulting in intermittent bugs.
+       Putting this call here avoids all that crud.
+
+       The EQ test avoids infinite recursion.  */
+    if (! NILP (default_directory) && !EQ (default_directory, name)
+       /* Save time in some common cases - as long as default_directory
+          is not relative, it can be canonicalized with name below (if it
+          is needed at all) without requiring it to be expanded now.  */
 #ifdef DOS_NT
-      /* Detect MSDOS file names with drive specifiers.  */
-      && ! (IS_DRIVE (o[0]) && IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))
+       /* Detect MSDOS file names with drive specifiers.  */
+       && ! (IS_DRIVE (o[0]) && IS_DEVICE_SEP (o[1])
+             && IS_DIRECTORY_SEP (o[2]))
 #ifdef WINDOWSNT
-      /* Detect Windows file names in UNC format.  */
-      && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
+       /* Detect Windows file names in UNC format.  */
+       && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
 #endif
 #else /* not DOS_NT */
       /* Detect Unix absolute file names (/... alone is not absolute on
         DOS or Windows).  */
-      && ! (IS_DIRECTORY_SEP (o[0]))
+       && ! (IS_DIRECTORY_SEP (o[0]))
 #endif /* not DOS_NT */
-      )
-    {
-      struct gcpro gcpro1;
-
-      GCPRO1 (name);
-      default_directory = Fexpand_file_name (default_directory, Qnil);
-      UNGCPRO;
-    }
+       )
+      {
+       struct gcpro gcpro1;
 
+       GCPRO1 (name);
+       default_directory = Fexpand_file_name (default_directory, Qnil);
+       UNGCPRO;
+      }
+  }
   name = FILE_SYSTEM_CASE (name);
   multibyte = STRING_MULTIBYTE (name);
   if (multibyte != STRING_MULTIBYTE (default_directory))
@@ -1150,11 +922,13 @@ See also the function `substitute-in-file-name'.  */)
     }
 
   nm = SDATA (name);
+  nm_in_name = 1;
 
 #ifdef DOS_NT
   /* We will force directory separators to be either all \ or /, so make
      a local copy to modify, even if there ends up being no change. */
   nm = strcpy (alloca (strlen (nm) + 1), nm);
+  nm_in_name = 0;
 
   /* Note if special escape prefix is present, but remove for now.  */
   if (nm[0] == '/' && nm[1] == ':')
@@ -1178,16 +952,14 @@ See also the function `substitute-in-file-name'.  */)
      "//somedir".  */
   if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
     nm++;
-#endif /* WINDOWSNT */
-#endif /* DOS_NT */
 
-#ifdef WINDOWSNT
   /* Discard any previous drive specifier if nm is now in UNC format. */
   if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
     {
       drive = 0;
     }
-#endif
+#endif /* WINDOWSNT */
+#endif /* DOS_NT */
 
   /* If nm is absolute, look for `/./' or `/../' or `//''sequences; if
      none are found, we can probably return right away.  We will avoid
@@ -1200,9 +972,6 @@ See also the function `substitute-in-file-name'.  */)
 #ifdef WINDOWSNT
       && (drive || IS_DIRECTORY_SEP (nm[1])) && !is_escaped
 #endif
-#ifdef VMS
-      || index (nm, ':')
-#endif /* VMS */
       )
     {
       /* If it turns out that the filename we want to return is just a
@@ -1212,8 +981,8 @@ See also the function `substitute-in-file-name'.  */)
         non-zero value, that means we've discovered that we can't do
         that cool trick.  */
       int lose = 0;
+      unsigned char *p = nm;
 
-      p = nm;
       while (*p)
        {
          /* Since we know the name is absolute, we can assume that each
@@ -1233,91 +1002,10 @@ See also the function `substitute-in-file-name'.  */)
                   && IS_DIRECTORY_SEP (p[0])
                   && IS_DIRECTORY_SEP (p[1]))
            lose = 1;
-
-#ifdef VMS
-         if (p[0] == '\\')
-           lose = 1;
-         if (p[0] == '/') {
-           /* if dev:[dir]/, move nm to / */
-           if (!slash && p > nm && (brack || colon)) {
-             nm = (brack ? brack + 1 : colon + 1);
-             lbrack = rbrack = 0;
-             brack = 0;
-             colon = 0;
-           }
-           slash = p;
-         }
-         if (p[0] == '-')
-#ifdef NO_HYPHENS_IN_FILENAMES
-           if (lbrack == rbrack)
-             {
-                /* Avoid clobbering negative version numbers.  */
-                if (dots < 2)
-                 p[0] = '_';
-             }
-           else
-#endif /* NO_HYPHENS_IN_FILENAMES */
-             if (lbrack > rbrack
-                 && ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<')
-                     && (p[1] == '.' || p[1] == ']' || p[1] == '>')))
-               lose = 1;
-#ifdef NO_HYPHENS_IN_FILENAMES
-             else
-               p[0] = '_';
-#endif /* NO_HYPHENS_IN_FILENAMES */
-         /* count open brackets, reset close bracket pointer */
-         if (p[0] == '[' || p[0] == '<')
-           lbrack++, brack = 0;
-         /* count close brackets, set close bracket pointer */
-         if (p[0] == ']' || p[0] == '>')
-           rbrack++, brack = p;
-         /* detect ][ or >< */
-         if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
-           lose = 1;
-         if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
-           nm = p + 1, lose = 1;
-         if (p[0] == ':' && (colon || slash))
-           /* if dev1:[dir]dev2:, move nm to dev2: */
-           if (brack)
-             {
-               nm = brack + 1;
-               brack = 0;
-             }
-           /* if /name/dev:, move nm to dev: */
-           else if (slash)
-             nm = slash + 1;
-           /* if node::dev:, move colon following dev */
-           else if (colon && colon[-1] == ':')
-             colon = p;
-           /* if dev1:dev2:, move nm to dev2: */
-           else if (colon && colon[-1] != ':')
-             {
-               nm = colon + 1;
-               colon = 0;
-             }
-         if (p[0] == ':' && !colon)
-           {
-             if (p[1] == ':')
-               p++;
-             colon = p;
-           }
-         if (lbrack == rbrack)
-           if (p[0] == ';')
-             dots = 2;
-           else if (p[0] == '.')
-             dots++;
-#endif /* VMS */
          p++;
        }
       if (!lose)
        {
-#ifdef VMS
-         if (index (nm, '/'))
-           {
-             nm = sys_translate_unix (nm);
-             return make_specified_string (nm, -1, strlen (nm), multibyte);
-           }
-#endif /* VMS */
 #ifdef DOS_NT
          /* Make sure directories are all separated with / or \ as
             desired, but avoid allocation of a new string when not
@@ -1370,29 +1058,35 @@ See also the function `substitute-in-file-name'.  */)
   if (nm[0] == '~')            /* prefix ~ */
     {
       if (IS_DIRECTORY_SEP (nm[1])
-#ifdef VMS
-         || nm[1] == ':'
-#endif /* VMS */
          || nm[1] == 0)        /* ~ by itself */
        {
+         Lisp_Object tem;
+
          if (!(newdir = (unsigned char *) egetenv ("HOME")))
            newdir = (unsigned char *) "";
          nm++;
+         /* egetenv may return a unibyte string, which will bite us since
+            we expect the directory to be multibyte.  */
+         tem = build_string (newdir);
+         if (!STRING_MULTIBYTE (tem))
+           {
+             /* FIXME: DECODE_FILE may GC, which may move SDATA(name),
+                after which `nm' won't point to the right place any more.  */
+             int offset = nm - SDATA (name);
+             hdir = DECODE_FILE (tem);
+             newdir = SDATA (hdir);
+             if (nm_in_name)
+             nm = SDATA (name) + offset;
+           }
 #ifdef DOS_NT
          collapse_newdir = 0;
 #endif
-#ifdef VMS
-         nm++;                 /* Don't leave the slash in nm.  */
-#endif /* VMS */
        }
       else                     /* ~user/filename */
        {
-         for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)
-#ifdef VMS
-                             && *p != ':'
-#endif /* VMS */
-                             ); p++);
-         o = (unsigned char *) alloca (p - nm + 1);
+         unsigned char *o, *p;
+         for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++);
+         o = alloca (p - nm + 1);
          bcopy ((char *) nm, o, p - nm);
          o [p - nm] = 0;
 
@@ -1402,14 +1096,10 @@ See also the function `substitute-in-file-name'.  */)
          if (pw)
            {
              newdir = (unsigned char *) pw -> pw_dir;
-#ifdef VMS
-             nm = p + 1;       /* skip the terminator */
-#else
              nm = p;
 #ifdef DOS_NT
              collapse_newdir = 0;
 #endif
-#endif /* VMS */
            }
 
          /* If we don't find a user of that name, leave the name
@@ -1451,9 +1141,6 @@ See also the function `substitute-in-file-name'.  */)
 #endif
 #ifdef WINDOWSNT
       && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
-#endif
-#ifdef VMS
-      && !index (nm, ':')
 #endif
       && !newdir)
     {
@@ -1524,6 +1211,7 @@ See also the function `substitute-in-file-name'.  */)
 #ifdef WINDOWSNT
          if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
            {
+             unsigned char *p;
              newdir = strcpy (alloca (strlen (newdir) + 1), newdir);
              p = newdir + 2;
              while (*p && !IS_DIRECTORY_SEP (*p)) p++;
@@ -1574,7 +1262,6 @@ See also the function `substitute-in-file-name'.  */)
 
   if (newdir)
     {
-#ifndef VMS
       if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
        {
 #ifdef DOS_NT
@@ -1589,135 +1276,86 @@ See also the function `substitute-in-file-name'.  */)
            strcpy (target, newdir);
        }
       else
-#endif
        file_name_as_directory (target, newdir);
     }
 
   strcat (target, nm);
-#ifdef VMS
-  if (index (target, '/'))
-    strcpy (target, sys_translate_unix (target));
-#endif /* VMS */
-
-  /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
 
   /* Now canonicalize by removing `//', `/.' and `/foo/..' if they
      appear.  */
+  {
+    unsigned char *p = target;
+    unsigned char *o = target;
 
-  p = target;
-  o = target;
-
-  while (*p)
-    {
-#ifdef VMS
-      if (*p != ']' && *p != '>' && *p != '-')
-       {
-         if (*p == '\\')
-           p++;
-         *o++ = *p++;
-       }
-      else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
-       /* brackets are offset from each other by 2 */
-       {
-         p += 2;
-         if (*p != '.' && *p != '-' && o[-1] != '.')
-           /* convert [foo][bar] to [bar] */
-           while (o[-1] != '[' && o[-1] != '<')
-             o--;
-         else if (*p == '-' && *o != '.')
-           *--p = '.';
-       }
-      else if (p[0] == '-' && o[-1] == '.'
-              && (p[1] == '.' || p[1] == ']' || p[1] == '>'))
-       /* flush .foo.- ; leave - if stopped by '[' or '<' */
-       {
-         do
-           o--;
-         while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
-         if (p[1] == '.')      /* foo.-.bar ==> bar.  */
+    while (*p)
+      {
+       if (!IS_DIRECTORY_SEP (*p))
+         {
+           *o++ = *p++;
+         }
+       else if (p[1] == '.'
+                && (IS_DIRECTORY_SEP (p[2])
+                    || p[2] == 0))
+         {
+           /* If "/." is the entire filename, keep the "/".  Otherwise,
+              just delete the whole "/.".  */
+           if (o == target && p[2] == '\0')
+             *o++ = *p;
            p += 2;
-         else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
-           p++, o--;
-         /* else [foo.-] ==> [-] */
-       }
-      else
-       {
-#ifdef NO_HYPHENS_IN_FILENAMES
-         if (*p == '-'
-             && o[-1] != '[' && o[-1] != '<' && o[-1] != '.'
-             && p[1] != ']' && p[1] != '>' && p[1] != '.')
-           *p = '_';
-#endif /* NO_HYPHENS_IN_FILENAMES */
-         *o++ = *p++;
-       }
-#else /* not VMS */
-      if (!IS_DIRECTORY_SEP (*p))
-       {
-         *o++ = *p++;
-       }
-      else if (p[1] == '.'
-              && (IS_DIRECTORY_SEP (p[2])
-                  || p[2] == 0))
-       {
-         /* If "/." is the entire filename, keep the "/".  Otherwise,
-            just delete the whole "/.".  */
-         if (o == target && p[2] == '\0')
-           *o++ = *p;
-         p += 2;
-       }
-      else if (p[1] == '.' && p[2] == '.'
-              /* `/../' is the "superroot" on certain file systems.
-                 Turned off on DOS_NT systems because they have no
-                 "superroot" and because this causes us to produce
-                 file names like "d:/../foo" which fail file-related
-                 functions of the underlying OS.  (To reproduce, try a
-                 long series of "../../" in default_directory, longer
-                 than the number of levels from the root.)  */
+         }
+       else if (p[1] == '.' && p[2] == '.'
+                /* `/../' is the "superroot" on certain file systems.
+                   Turned off on DOS_NT systems because they have no
+                   "superroot" and because this causes us to produce
+                   file names like "d:/../foo" which fail file-related
+                   functions of the underlying OS.  (To reproduce, try a
+                   long series of "../../" in default_directory, longer
+                   than the number of levels from the root.)  */
 #ifndef DOS_NT
-              && o != target
+                && o != target
 #endif
-              && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
-       {
-         while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
-           ;
-         /* Keep initial / only if this is the whole name.  */
-         if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
-           ++o;
-         p += 3;
-       }
-      else if (p > target && IS_DIRECTORY_SEP (p[1]))
-       /* Collapse multiple `/' in a row.  */
-       p++;
-      else
-       {
-         *o++ = *p++;
-       }
-#endif /* not VMS */
-    }
+                && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
+         {
+           while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
+             ;
+           /* Keep initial / only if this is the whole name.  */
+           if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
+             ++o;
+           p += 3;
+         }
+       else if (p > target && IS_DIRECTORY_SEP (p[1]))
+         /* Collapse multiple `/' in a row.  */
+         p++;
+       else
+         {
+           *o++ = *p++;
+         }
+      }
 
 #ifdef DOS_NT
-  /* At last, set drive name. */
+    /* At last, set drive name. */
 #ifdef WINDOWSNT
-  /* Except for network file name.  */
-  if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
+    /* Except for network file name.  */
+    if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
 #endif /* WINDOWSNT */
-    {
-      if (!drive) abort ();
-      target -= 2;
-      target[0] = DRIVE_LETTER (drive);
-      target[1] = ':';
-    }
-  /* Reinsert the escape prefix if required.  */
-  if (is_escaped)
-    {
-      target -= 2;
-      target[0] = '/';
-      target[1] = ':';
-    }
-  CORRECT_DIR_SEPS (target);
+      {
+       if (!drive) abort ();
+       target -= 2;
+       target[0] = DRIVE_LETTER (drive);
+       target[1] = ':';
+      }
+    /* Reinsert the escape prefix if required.  */
+    if (is_escaped)
+      {
+       target -= 2;
+       target[0] = '/';
+       target[1] = ':';
+      }
+    CORRECT_DIR_SEPS (target);
 #endif /* DOS_NT */
 
-  result = make_specified_string (target, -1, o - target, multibyte);
+    result = make_specified_string (target, -1, o - target, multibyte);
+  }
 
   /* Again look to see if the file name has special constructs in it
      and perhaps call the corresponding file handler.  This is needed
@@ -1761,32 +1399,13 @@ See also the function `substitute-in-file-name'.")
   unsigned char *target;
   struct passwd *pw;
   int lose;
-#ifdef VMS
-  unsigned char * colon = 0;
-  unsigned char * close = 0;
-  unsigned char * slash = 0;
-  unsigned char * brack = 0;
-  int lbrack = 0, rbrack = 0;
-  int dots = 0;
-#endif /* VMS */
 
   CHECK_STRING (name);
-
-#ifdef VMS
-  /* Filenames on VMS are always upper case.  */
-  name = Fupcase (name);
-#endif
-
   nm = SDATA (name);
 
   /* If nm is absolute, flush ...// and detect /./ and /../.
      If no /./ or /../ we can return right away.  */
-  if (
-      nm[0] == '/'
-#ifdef VMS
-      || index (nm, ':')
-#endif /* VMS */
-      )
+  if (nm[0] == '/')
     {
       p = nm;
       lose = 0;
@@ -1801,87 +1420,10 @@ See also the function `substitute-in-file-name'.")
              && (p[2] == '/' || p[2] == 0
                  || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
            lose = 1;
-#ifdef VMS
-         if (p[0] == '\\')
-           lose = 1;
-         if (p[0] == '/') {
-           /* if dev:[dir]/, move nm to / */
-           if (!slash && p > nm && (brack || colon)) {
-             nm = (brack ? brack + 1 : colon + 1);
-             lbrack = rbrack = 0;
-             brack = 0;
-             colon = 0;
-           }
-           slash = p;
-         }
-         if (p[0] == '-')
-#ifndef VMS4_4
-           /* VMS pre V4.4,convert '-'s in filenames. */
-           if (lbrack == rbrack)
-             {
-               if (dots < 2)   /* this is to allow negative version numbers */
-                 p[0] = '_';
-             }
-           else
-#endif /* VMS4_4 */
-             if (lbrack > rbrack
-                 && ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<')
-                     && (p[1] == '.' || p[1] == ']' || p[1] == '>')))
-               lose = 1;
-#ifndef VMS4_4
-             else
-               p[0] = '_';
-#endif /* VMS4_4 */
-         /* count open brackets, reset close bracket pointer */
-         if (p[0] == '[' || p[0] == '<')
-           lbrack++, brack = 0;
-         /* count close brackets, set close bracket pointer */
-         if (p[0] == ']' || p[0] == '>')
-           rbrack++, brack = p;
-         /* detect ][ or >< */
-         if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
-           lose = 1;
-         if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
-           nm = p + 1, lose = 1;
-         if (p[0] == ':' && (colon || slash))
-           /* if dev1:[dir]dev2:, move nm to dev2: */
-           if (brack)
-             {
-               nm = brack + 1;
-               brack = 0;
-             }
-           /* If /name/dev:, move nm to dev: */
-           else if (slash)
-             nm = slash + 1;
-           /* If node::dev:, move colon following dev */
-           else if (colon && colon[-1] == ':')
-             colon = p;
-           /* If dev1:dev2:, move nm to dev2: */
-           else if (colon && colon[-1] != ':')
-             {
-               nm = colon + 1;
-               colon = 0;
-             }
-         if (p[0] == ':' && !colon)
-           {
-             if (p[1] == ':')
-               p++;
-             colon = p;
-           }
-         if (lbrack == rbrack)
-           if (p[0] == ';')
-             dots = 2;
-           else if (p[0] == '.')
-             dots++;
-#endif /* VMS */
          p++;
        }
       if (!lose)
        {
-#ifdef VMS
-         if (index (nm, '/'))
-           return build_string (sys_translate_unix (nm));
-#endif /* VMS */
          if (nm == SDATA (name))
            return name;
          return build_string (nm);
@@ -1893,18 +1435,11 @@ See also the function `substitute-in-file-name'.")
   newdir = 0;
 
   if (nm[0] == '~')             /* prefix ~ */
-    if (nm[1] == '/'
-#ifdef VMS
-       || nm[1] == ':'
-#endif /* VMS */
-       || nm[1] == 0)/* ~/filename */
+    if (nm[1] == '/' || nm[1] == 0)/* ~/filename */
       {
        if (!(newdir = (unsigned char *) egetenv ("HOME")))
          newdir = (unsigned char *) "";
        nm++;
-#ifdef VMS
-       nm++;                   /* Don't leave the slash in nm.  */
-#endif /* VMS */
       }
     else  /* ~user/filename */
       {
@@ -1913,11 +1448,6 @@ See also the function `substitute-in-file-name'.")
        /* Find end of name. */
        unsigned char *ptr = (unsigned char *) index (user, '/');
        int len = ptr ? ptr - user : strlen (user);
-#ifdef VMS
-       unsigned char *ptr1 = index (user, ':');
-       if (ptr1 != 0 && ptr1 - user < len)
-         len = ptr1 - user;
-#endif /* VMS */
        /* Copy the user name into temp storage. */
        o = (unsigned char *) alloca (len + 1);
        bcopy ((char *) user, o, len);
@@ -1936,11 +1466,7 @@ See also the function `substitute-in-file-name'.")
        nm += len;
       }
 
-  if (nm[0] != '/'
-#ifdef VMS
-      && !index (nm, ':')
-#endif /* not VMS */
-      && !newdir)
+  if (nm[0] != '/' && !newdir)
     {
       if (NILP (defalt))
        defalt = current_buffer->directory;
@@ -1956,19 +1482,13 @@ See also the function `substitute-in-file-name'.")
 
   if (newdir)
     {
-#ifndef VMS
       if (nm[0] == 0 || nm[0] == '/')
        strcpy (target, newdir);
       else
-#endif
       file_name_as_directory (target, newdir);
     }
 
   strcat (target, nm);
-#ifdef VMS
-  if (index (target, '/'))
-    strcpy (target, sys_translate_unix (target));
-#endif /* VMS */
 
   /* Now canonicalize by removing /. and /foo/.. if they appear */
 
@@ -1977,48 +1497,6 @@ See also the function `substitute-in-file-name'.")
 
   while (*p)
     {
-#ifdef VMS
-      if (*p != ']' && *p != '>' && *p != '-')
-       {
-         if (*p == '\\')
-           p++;
-         *o++ = *p++;
-       }
-      else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
-       /* brackets are offset from each other by 2 */
-       {
-         p += 2;
-         if (*p != '.' && *p != '-' && o[-1] != '.')
-           /* convert [foo][bar] to [bar] */
-           while (o[-1] != '[' && o[-1] != '<')
-             o--;
-         else if (*p == '-' && *o != '.')
-           *--p = '.';
-       }
-      else if (p[0] == '-' && o[-1] == '.'
-              && (p[1] == '.' || p[1] == ']' || p[1] == '>'))
-       /* flush .foo.- ; leave - if stopped by '[' or '<' */
-       {
-         do
-           o--;
-         while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
-         if (p[1] == '.')      /* foo.-.bar ==> bar.  */
-           p += 2;
-         else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
-           p++, o--;
-         /* else [foo.-] ==> [-] */
-       }
-      else
-       {
-#ifndef VMS4_4
-         if (*p == '-'
-             && o[-1] != '[' && o[-1] != '<' && o[-1] != '.'
-             && p[1] != ']' && p[1] != '>' && p[1] != '.')
-           *p = '_';
-#endif /* VMS4_4 */
-         *o++ = *p++;
-       }
-#else /* not VMS */
       if (*p != '/')
        {
          *o++ = *p++;
@@ -2047,7 +1525,6 @@ See also the function `substitute-in-file-name'.")
        {
          *o++ = *p++;
        }
-#endif /* not VMS */
     }
 
   return make_string (target, o - target);
@@ -2061,13 +1538,6 @@ file_name_absolute_p (filename)
 {
   return
     (IS_DIRECTORY_SEP (*filename) || *filename == '~'
-#ifdef VMS
-     /* ??? This criterion is probably wrong for '<'.  */
-     || index (filename, ':') || index (filename, '<')
-     || (*filename == '[' && (filename[1] != '-'
-                             || (filename[2] != '.' && filename[2] != ']'))
-        && filename[1] != '.')
-#endif /* VMS */
 #ifdef DOS_NT
      || (IS_DRIVE (*filename) && IS_DEVICE_SEP (filename[1])
         && IS_DIRECTORY_SEP (filename[2]))
@@ -2084,9 +1554,6 @@ search_embedded_absfilename (nm, endp)
   for (p = nm + 1; p < endp; p++)
     {
       if ((0
-#ifdef VMS
-          || p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
-#endif /* VMS */
           || IS_DIRECTORY_SEP (p[-1]))
          && file_name_absolute_p (p)
 #if defined (WINDOWSNT) || defined(CYGWIN)
@@ -2096,11 +1563,7 @@ search_embedded_absfilename (nm, endp)
 #endif /* not (WINDOWSNT || CYGWIN) */
              )
        {
-         for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
-#ifdef VMS
-                             && *s != ':'
-#endif /* VMS */
-                             ); s++);
+         for (s = p; *s && (!IS_DIRECTORY_SEP (*s)); s++);
          if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
            {
              unsigned char *o = alloca (s - p + 1);
@@ -2131,10 +1594,7 @@ DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
 the value of that variable.  The variable name should be terminated
 with a character not a letter, digit or underscore; otherwise, enclose
 the entire variable name in braces.
-If `/~' appears, all of FILENAME through that `/' is discarded.
-
-On VMS, `$' substitution is not done; this function does little and only
-duplicates what `expand-file-name' does.  */)
+If `/~' appears, all of FILENAME through that `/' is discarded.  */)
      (filename)
      Lisp_Object filename;
 {
@@ -2173,9 +1633,6 @@ duplicates what `expand-file-name' does.  */)
       (make_specified_string (p, -1, endp - p,
                              STRING_MULTIBYTE (filename)));
 
-#ifdef VMS
-  return filename;
-#else
 
   /* See if any variables are substituted into the string
      and find the total length of their values in `total' */
@@ -2221,8 +1678,8 @@ duplicates what `expand-file-name' does.  */)
        /* Get variable value */
        o = (unsigned char *) egetenv (target);
        if (o)
-         {
-           total += strlen (o);
+         { /* Eight-bit chars occupy upto 2 bytes in multibyte.  */
+           total += strlen (o) * (STRING_MULTIBYTE (filename) ? 2 : 1);
            substituted = 1;
          }
        else if (*p == '}')
@@ -2317,7 +1774,6 @@ duplicates what `expand-file-name' does.  */)
   error ("Substituting nonexistent environment variable \"%s\"", target);
 
   /* NOTREACHED */
-#endif /* not VMS */
   return Qnil;
 }
 \f
@@ -2331,13 +1787,7 @@ expand_and_dir_to_file (filename, defdir)
   register Lisp_Object absname;
 
   absname = Fexpand_file_name (filename, defdir);
-#ifdef VMS
-  {
-    register int c = SREF (absname, SBYTES (absname) - 1);
-    if (c == ':' || c == ']' || c == '>')
-      absname = Fdirectory_file_name (absname);
-  }
-#else
+
   /* Remove final slash, if any (unless this is the root dir).
      stat behaves differently depending!  */
   if (SCHARS (absname) > 1
@@ -2345,7 +1795,6 @@ expand_and_dir_to_file (filename, defdir)
       && !IS_DEVICE_SEP (SREF (absname, SBYTES (absname)-2)))
     /* We cannot take shortcuts; they might be wrong for magic file names.  */
     absname = Fdirectory_file_name (absname);
-#endif
   return absname;
 }
 \f
@@ -2538,10 +1987,6 @@ uid and gid of FILE to NEWNAME.  */)
     }
 #endif /* S_ISREG && S_ISLNK */
 
-#ifdef VMS
-  /* Create the copy file with the same record format as the input file */
-  ofd = sys_creat (SDATA (encoded_newname), 0666, ifd);
-#else
 #ifdef MSDOS
   /* System's default file type was set to binary by _fmode in emacs.c.  */
   ofd = emacs_open (SDATA (encoded_newname),
@@ -2554,7 +1999,6 @@ uid and gid of FILE to NEWNAME.  */)
                    | (NILP (ok_if_already_exists) ? O_EXCL : 0),
                    0666);
 #endif /* not MSDOS */
-#endif /* VMS */
   if (ofd < 0)
     report_file_error ("Opening output file", Fcons (newname, Qnil));
 
@@ -2665,6 +2109,9 @@ DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete
   if (!NILP (handler))
     return call2 (handler, Qdelete_directory, directory);
 
+  if (delete_by_moving_to_trash)
+    return call1 (Qmove_file_to_trash, directory);
+
   encoded_dir = ENCODE_FILE (directory);
 
   dir = SDATA (encoded_dir);
@@ -2698,6 +2145,9 @@ If file has multiple names, it continues to exist with the other names.  */)
   if (!NILP (handler))
     return call2 (handler, Qdelete_file, filename);
 
+  if (delete_by_moving_to_trash)
+    return call1 (Qmove_file_to_trash, filename);
+
   encoded_file = ENCODE_FILE (filename);
 
   if (0 > unlink (SDATA (encoded_file)))
@@ -2778,12 +2228,7 @@ This is what happens in interactive use with M-x.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (newname, "rename to it",
                                  INTEGERP (ok_if_already_exists), 0, 0);
-#ifndef BSD4_1
   if (0 > rename (SDATA (encoded_file), SDATA (encoded_newname)))
-#else
-  if (0 > link (SDATA (encoded_file), SDATA (encoded_newname))
-      || 0 > unlink (SDATA (encoded_file)))
-#endif
     {
       if (errno == EXDEV)
        {
@@ -2864,7 +2309,6 @@ This is what happens in interactive use with M-x.  */)
   return Qnil;
 }
 
-#ifdef S_IFLNK
 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
        "FMake symbolic link to file: \nGMake symbolic link to file %s: \np",
        doc: /* Make a symbolic link to FILENAME, named LINKNAME.
@@ -2909,6 +2353,7 @@ This happens for interactive use with M-x.  */)
     RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
                           linkname, ok_if_already_exists));
 
+#ifdef S_IFLNK
   encoded_filename = ENCODE_FILE (filename);
   encoded_linkname = ENCODE_FILE (linkname);
 
@@ -2935,56 +2380,14 @@ This happens for interactive use with M-x.  */)
     }
   UNGCPRO;
   return Qnil;
-}
-#endif /* S_IFLNK */
-
-#ifdef VMS
-
-DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
-       2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
-       doc: /* Define the job-wide logical name NAME to have the value STRING.
-If STRING is nil or a null string, the logical name NAME is deleted.  */)
-     (name, string)
-     Lisp_Object name;
-     Lisp_Object string;
-{
-  CHECK_STRING (name);
-  if (NILP (string))
-    delete_logical_name (SDATA (name));
-  else
-    {
-      CHECK_STRING (string);
 
-      if (SCHARS (string) == 0)
-       delete_logical_name (SDATA (name));
-      else
-       define_logical_name (SDATA (name), SDATA (string));
-    }
+#else
+  UNGCPRO;
+  xsignal1 (Qfile_error, build_string ("Symbolic links are not supported"));
 
-  return string;
+#endif /* S_IFLNK */
 }
-#endif /* VMS */
-
-#ifdef HPUX_NET
-
-DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
-       doc: /* Open a network connection to PATH using LOGIN as the login string.  */)
-     (path, login)
-     Lisp_Object path, login;
-{
-  int netresult;
-
-  CHECK_STRING (path);
-  CHECK_STRING (login);
-
-  netresult = netunam (SDATA (path), SDATA (login));
 
-  if (netresult == -1)
-    return Qnil;
-  else
-    return Qt;
-}
-#endif /* HPUX_NET */
 \f
 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
        1, 1, 0,
@@ -3014,9 +2417,9 @@ check_executable (filename)
 #else
   return (S_ISREG (st.st_mode)
          && len >= 5
-         && (stricmp ((suffix = filename + len-4), ".com") == 0
-             || stricmp (suffix, ".exe") == 0
-             || stricmp (suffix, ".bat") == 0)
+         && (xstrcasecmp ((suffix = filename + len-4), ".com") == 0
+             || xstrcasecmp (suffix, ".exe") == 0
+             || xstrcasecmp (suffix, ".bat") == 0)
          || (st.st_mode & S_IFMT) == S_IFDIR);
 #endif /* not WINDOWSNT */
 #else /* not DOS_NT */
@@ -3180,10 +2583,6 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
            ? Qt : Qnil);
 
   dir = Ffile_name_directory (absname);
-#ifdef VMS
-  if (!NILP (dir))
-    dir = Fdirectory_file_name (dir);
-#endif /* VMS */
 #ifdef MSDOS
   if (!NILP (dir))
     dir = Fdirectory_file_name (dir);
@@ -3713,6 +3112,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   struct stat st;
   register int fd;
   int inserted = 0;
+  int nochange = 0;
   register int how_much;
   register int unprocessed;
   int count = SPECPDL_INDEX ();
@@ -3820,10 +3220,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
   record_unwind_protect (close_file_unwind, make_number (fd));
 
-  /* Supposedly happens on VMS.  */
   /* Can happen on any platform that uses long as type of off_t, but allows
-     file sizes to exceed 2Gb.  VMS is no longer officially supported, so
-     give a message suitable for the latter case.  */
+     file sizes to exceed 2Gb, so give a suitable message.  */
   if (! not_regular && st.st_size < 0)
     error ("Maximum buffer size exceeded");
 
@@ -4233,8 +3631,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
          how_much += this;
 
-         BUF_SET_PT (XBUFFER (conversion_buffer),
-                     BUF_Z (XBUFFER (conversion_buffer)));
+         BUF_TEMP_SET_PT (XBUFFER (conversion_buffer),
+                          BUF_Z (XBUFFER (conversion_buffer)));
          decode_coding_c_string (&coding, read_buf, unprocessed + this,
                                  conversion_buffer);
          unprocessed = coding.carryover_bytes;
@@ -4278,7 +3676,10 @@ variable `last-coding-system-used' to the coding system actually used.  */)
        {
          specpdl_ptr--;
          /* Truncate the buffer to the size of the file.  */
-         del_range_byte (same_at_start, same_at_end, 0);
+         if (same_at_start == same_at_end)
+           nochange = 1;
+         else
+           del_range_byte (same_at_start, same_at_end, 0);
          inserted = 0;
 
          unbind_to (this_count, Qnil);
@@ -4625,7 +4026,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
   if (!NILP (visit))
     {
-      if (!EQ (current_buffer->undo_list, Qt))
+      if (!EQ (current_buffer->undo_list, Qt) && !nochange)
        current_buffer->undo_list = Qnil;
 
       if (NILP (handler))
@@ -4664,15 +4065,16 @@ variable `last-coding-system-used' to the coding system actually used.  */)
        }
     }
 
-  /* Decode file format */
+  /* Decode file format */
   if (inserted > 0)
     {
-      /* Don't run point motion or modification hooks when decoding. */
+      /* Don't run point motion or modification hooks when decoding.  */
       int count = SPECPDL_INDEX ();
+      int old_inserted = inserted;
       specbind (Qinhibit_point_motion_hooks, Qt);
       specbind (Qinhibit_modification_hooks, Qt);
 
-      /* Save old undo list and don't record undo for decoding. */
+      /* Save old undo list and don't record undo for decoding.  */
       old_undo = current_buffer->undo_list;
       current_buffer->undo_list = Qt;
 
@@ -4686,14 +4088,14 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       else
        {
          /* If REPLACE is non-nil and we succeeded in not replacing the
-         beginning or end of the buffer text with the file's contents,
-         call format-decode with `point' positioned at the beginning of
-         the buffer and `inserted' equalling the number of characters
-         in the buffer.  Otherwise, format-decode might fail to
-         correctly analyze the beginning or end of the buffer.  Hence
-         we temporarily save `point' and `inserted' here and restore
-         `point' iff format-decode did not insert or delete any text.
-         Otherwise we leave `point' at point-min. */
+            beginning or end of the buffer text with the file's contents,
+            call format-decode with `point' positioned at the beginning
+            of the buffer and `inserted' equalling the number of
+            characters in the buffer.  Otherwise, format-decode might
+            fail to correctly analyze the beginning or end of the buffer.
+            Hence we temporarily save `point' and `inserted' here and
+            restore `point' iff format-decode did not insert or delete
+            any text.  Otherwise we leave `point' at point-min.  */
          int opoint = PT;
          int opoint_byte = PT_BYTE;
          int oinserted = ZV - BEGV;
@@ -4706,16 +4108,16 @@ variable `last-coding-system-used' to the coding system actually used.  */)
          if (ochars_modiff == CHARS_MODIFF)
            /* format_decode didn't modify buffer's characters => move
               point back to position before inserted text and leave
-              value of inserted alone. */
+              value of inserted alone.  */
            SET_PT_BOTH (opoint, opoint_byte);
          else
            /* format_decode modified buffer's characters => consider
-              entire buffer changed and leave point at point-min. */
+              entire buffer changed and leave point at point-min.  */
            inserted = XFASTINT (insval);
        }
 
       /* For consistency with format-decode call these now iff inserted > 0
-        (martin 2007-06-28) */
+        (martin 2007-06-28) */
       p = Vafter_insert_file_functions;
       while (CONSP (p))
        {
@@ -4730,7 +4132,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
            }
          else
            {
-             /* For the rationale of this see the comment on format-decode above. */
+             /* For the rationale of this see the comment on
+                format-decode above.  */
              int opoint = PT;
              int opoint_byte = PT_BYTE;
              int oinserted = ZV - BEGV;
@@ -4745,12 +4148,12 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                    /* after_insert_file_functions didn't modify
                       buffer's characters => move point back to
                       position before inserted text and leave value of
-                      inserted alone. */
+                      inserted alone.  */
                    SET_PT_BOTH (opoint, opoint_byte);
                  else
                    /* after_insert_file_functions did modify buffer's
                       characters => consider entire buffer changed and
-                      leave point at point-min. */
+                      leave point at point-min.  */
                    inserted = XFASTINT (insval);
                }
            }
@@ -4761,22 +4164,21 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (NILP (visit))
        {
-         Lisp_Object lbeg, lend;
-         XSETINT (lbeg, PT);
-         XSETINT (lend, PT + inserted);
-         if (CONSP (old_undo))
+         current_buffer->undo_list = old_undo;
+         if (CONSP (old_undo) && inserted != old_inserted)
            {
+             /* Adjust the last undo record for the size change during
+                the format conversion.  */
              Lisp_Object tem = XCAR (old_undo);
-             if (CONSP (tem) && INTEGERP (XCAR (tem)) &&
-                 INTEGERP (XCDR (tem)) && EQ (XCAR (tem), lbeg))
-               /* In the non-visiting case record only the final insertion. */
-               current_buffer->undo_list =
-                 Fcons (Fcons (lbeg, lend), Fcdr (old_undo));
+             if (CONSP (tem) && INTEGERP (XCAR (tem))
+                 && INTEGERP (XCDR (tem))
+                 && XFASTINT (XCDR (tem)) == PT + old_inserted)
+               XSETCDR (tem, make_number (PT + inserted));
            }
        }
       else
        /* If undo_list was Qt before, keep it that way.
-          Otherwise start with an empty undo_list. */
+          Otherwise start with an empty undo_list.  */
        current_buffer->undo_list = EQ (old_undo, Qt) ? Qt : Qnil;
 
       unbind_to (count, Qnil);
@@ -4988,9 +4390,6 @@ This does code conversion according to the value of
   struct stat st;
   int count = SPECPDL_INDEX ();
   int count1;
-#ifdef VMS
-  unsigned char *fname = 0;     /* If non-0, original filename (must rename) */
-#endif /* VMS */
   Lisp_Object handler;
   Lisp_Object visit_file;
   Lisp_Object annotations;
@@ -5056,8 +4455,11 @@ This does code conversion according to the value of
   /* Special kludge to simplify auto-saving.  */
   if (NILP (start))
     {
+      /* Do it later, so write-region-annotate-function can work differently
+        if we save "the buffer" vs "a region".
+        This is useful in tar-mode.  --Stef
       XSETFASTINT (start, BEG);
-      XSETFASTINT (end, Z);
+      XSETFASTINT (end, Z); */
       Fwiden ();
     }
 
@@ -5077,6 +4479,12 @@ This does code conversion according to the value of
        }
     }
 
+  if (NILP (start))
+    {
+      XSETFASTINT (start, BEGV);
+      XSETFASTINT (end, ZV);
+    }
+
   UNGCPRO;
 
   GCPRO5 (start, filename, annotations, visit_file, lockname);
@@ -5115,52 +4523,6 @@ This does code conversion according to the value of
 #endif /* not DOS_NT */
 
   if (desc < 0 && (NILP (append) || errno == ENOENT))
-#ifdef VMS
-    if (auto_saving)    /* Overwrite any previous version of autosave file */
-      {
-       vms_truncate (fn);      /* if fn exists, truncate to zero length */
-       desc = emacs_open (fn, O_RDWR, 0);
-       if (desc < 0)
-         desc = creat_copy_attrs (STRINGP (current_buffer->filename)
-                                  ? SDATA (current_buffer->filename) : 0,
-                                  fn);
-      }
-    else                /* Write to temporary name and rename if no errors */
-      {
-       Lisp_Object temp_name;
-       temp_name = Ffile_name_directory (filename);
-
-       if (!NILP (temp_name))
-         {
-           temp_name = Fmake_temp_name (concat2 (temp_name,
-                                                 build_string ("$$SAVE$$")));
-           fname = SDATA (filename);
-           fn = SDATA (temp_name);
-           desc = creat_copy_attrs (fname, fn);
-           if (desc < 0)
-             {
-               /* If we can't open the temporary file, try creating a new
-                  version of the original file.  VMS "creat" creates a
-                  new version rather than truncating an existing file. */
-               fn = fname;
-               fname = 0;
-               desc = creat (fn, 0666);
-#if 0 /* This can clobber an existing file and fail to replace it,
-        if the user runs out of space.  */
-               if (desc < 0)
-                 {
-                   /* We can't make a new version;
-                      try to truncate and rewrite existing version if any.  */
-                   vms_truncate (fn);
-                   desc = emacs_open (fn, O_RDWR, 0);
-                 }
-#endif
-             }
-         }
-       else
-         desc = creat (fn, 0666);
-      }
-#else /* not VMS */
 #ifdef DOS_NT
   desc = emacs_open (fn,
                     O_WRONLY | O_CREAT | buffer_file_type
@@ -5171,7 +4533,6 @@ This does code conversion according to the value of
                     | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
                     auto_saving ? auto_save_mode_bits : 0666);
 #endif /* not DOS_NT */
-#endif /* not VMS */
 
   if (desc < 0)
     {
@@ -5206,25 +4567,6 @@ This does code conversion according to the value of
 
   UNGCPRO;
 
-#ifdef VMS
-/*
- * Kludge Warning: The VMS C RTL likes to insert carriage returns
- * if we do writes that don't end with a carriage return. Furthermore
- * it cannot handle writes of more then 16K. The modified
- * version of "sys_write" in SYSDEP.C (see comment there) copes with
- * this EXCEPT for the last record (if it doesn't end with a carriage
- * return). This implies that if your buffer doesn't end with a carriage
- * return, you get one free... tough. However it also means that if
- * we make two calls to sys_write (a la the following code) you can
- * get one at the gap as well. The easiest way to fix this (honest)
- * is to move the gap to the next newline (or the end of the buffer).
- * Thus this change.
- *
- * Yech!
- */
-  if (GPT > BEG && GPT_ADDR[-1] != '\n')
-    move_gap (find_next_newline (GPT, 1));
-#else
 #if 0
   /* The new encoding routine doesn't require the following.  */
 
@@ -5240,7 +4582,6 @@ This does code conversion according to the value of
       move_gap_both (PT, PT_BYTE);
       SET_PT_BOTH (opoint, opoint_byte);
     }
-#endif
 #endif
 
   failure = 0;
@@ -5302,29 +4643,14 @@ This does code conversion according to the value of
      but who knows about all the other machines with NFS?)  */
 #if 0
 
-  /* On VMS, must do the stat after the close
-     since closing changes the modtime.  */
-#ifndef VMS
-  /* Recall that #if defined does not work on VMS.  */
 #define FOO
   fstat (desc, &st);
-#endif
 #endif
 
   /* NFS can report a write failure now.  */
   if (emacs_close (desc) < 0)
     failure = 1, save_errno = errno;
 
-#ifdef VMS
-  /* If we wrote to a temporary name and had no errors, rename to real name. */
-  if (fname)
-    {
-      if (!failure)
-       failure = (rename (fn, fname) != 0), save_errno = errno;
-      fn = fname;
-    }
-#endif /* VMS */
-
 #ifndef FOO
   stat (fn, &st);
 #endif
@@ -5728,6 +5054,8 @@ auto_save_error (error)
   char *msgbuf;
   USE_SAFE_ALLOCA;
 
+  auto_save_error_occurred = 1;
+
   ring_bell (XFRAME (selected_frame));
 
   args[0] = build_string ("Auto-saving %s: %s");
@@ -5774,9 +5102,9 @@ auto_save_1 ()
     }
 
   return
-    Fwrite_region (Qnil, Qnil,
-                  current_buffer->auto_save_file_name,
-                  Qnil, Qlambda, Qnil, Qnil);
+    Fwrite_region (Qnil, Qnil, current_buffer->auto_save_file_name, Qnil,
+                  NILP (Vauto_save_visited_file_name) ? Qlambda : Qt,
+                  Qnil, Qnil);
 }
 
 static Lisp_Object
@@ -5899,6 +5227,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
                         make_number (minibuffer_auto_raise));
   minibuffer_auto_raise = 0;
   auto_saving = 1;
+  auto_save_error_occurred = 0;
 
   /* On first pass, save all files that don't have handlers.
      On second pass, save all files that do have handlers.
@@ -6013,8 +5342,9 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
          sit_for (make_number (1), 0, 0);
          restore_message ();
        }
-      else
-       /* If we displayed a message and then restored a state
+      else if (!auto_save_error_occurred)
+       /* Don't overwrite the error message if an error occurred.
+          If we displayed a message and then restored a state
           with no message, leave a "done" message on the screen.  */
        message1 ("Auto-saving...done");
     }
@@ -6059,172 +5389,6 @@ then any auto-save counts as "recent".  */)
 }
 \f
 /* Reading and completing file names */
-extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
-extern Lisp_Object Qcompletion_ignore_case;
-
-/* In the string VAL, change each $ to $$ and return the result.  */
-
-static Lisp_Object
-double_dollars (val)
-     Lisp_Object val;
-{
-  register const unsigned char *old;
-  register unsigned char *new;
-  register int n;
-  int osize, count;
-
-  osize = SBYTES (val);
-
-  /* Count the number of $ characters.  */
-  for (n = osize, count = 0, old = SDATA (val); n > 0; n--)
-    if (*old++ == '$') count++;
-  if (count > 0)
-    {
-      old = SDATA (val);
-      val = make_uninit_multibyte_string (SCHARS (val) + count,
-                                         osize + count);
-      new = SDATA (val);
-      for (n = osize; n > 0; n--)
-       if (*old != '$')
-         *new++ = *old++;
-       else
-         {
-           *new++ = '$';
-           *new++ = '$';
-           old++;
-         }
-    }
-  return val;
-}
-
-static Lisp_Object
-read_file_name_cleanup (arg)
-     Lisp_Object arg;
-{
-  return (current_buffer->directory = arg);
-}
-
-DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
-       3, 3, 0,
-       doc: /* Internal subroutine for read-file-name.  Do not call this.  */)
-     (string, dir, action)
-     Lisp_Object string, dir, action;
-  /* action is nil for complete, t for return list of completions,
-     lambda for verify final value */
-{
-  Lisp_Object name, specdir, realdir, val, orig_string;
-  int changed;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-
-  CHECK_STRING (string);
-
-  realdir = dir;
-  name = string;
-  orig_string = Qnil;
-  specdir = Qnil;
-  changed = 0;
-  /* No need to protect ACTION--we only compare it with t and nil.  */
-  GCPRO5 (string, realdir, name, specdir, orig_string);
-
-  if (SCHARS (string) == 0)
-    {
-      if (EQ (action, Qlambda))
-       {
-         UNGCPRO;
-         return Qnil;
-       }
-    }
-  else
-    {
-      orig_string = string;
-      string = Fsubstitute_in_file_name (string);
-      changed = NILP (Fstring_equal (string, orig_string));
-      name = Ffile_name_nondirectory (string);
-      val = Ffile_name_directory (string);
-      if (! NILP (val))
-       realdir = Fexpand_file_name (val, realdir);
-    }
-
-  if (NILP (action))
-    {
-      specdir = Ffile_name_directory (string);
-      val = Ffile_name_completion (name, realdir, Vread_file_name_predicate);
-      UNGCPRO;
-      if (!STRINGP (val))
-       {
-         if (changed)
-           return double_dollars (string);
-         return val;
-       }
-
-      if (!NILP (specdir))
-       val = concat2 (specdir, val);
-#ifndef VMS
-      return double_dollars (val);
-#else /* not VMS */
-      return val;
-#endif /* not VMS */
-    }
-  UNGCPRO;
-
-  if (EQ (action, Qt))
-    {
-      Lisp_Object all = Ffile_name_all_completions (name, realdir);
-      Lisp_Object comp;
-      int count;
-
-      if (NILP (Vread_file_name_predicate)
-         || EQ (Vread_file_name_predicate, Qfile_exists_p))
-       return all;
-
-#ifndef VMS
-      if (EQ (Vread_file_name_predicate, Qfile_directory_p))
-       {
-         /* Brute-force speed up for directory checking:
-            Discard strings which don't end in a slash.  */
-         for (comp = Qnil; CONSP (all); all = XCDR (all))
-           {
-             Lisp_Object tem = XCAR (all);
-             int len;
-             if (STRINGP (tem) &&
-                 (len = SBYTES (tem), len > 0) &&
-                 IS_DIRECTORY_SEP (SREF (tem, len-1)))
-               comp = Fcons (tem, comp);
-           }
-       }
-      else
-#endif
-       {
-         /* Must do it the hard (and slow) way.  */
-         Lisp_Object tem;
-         GCPRO3 (all, comp, specdir);
-         count = SPECPDL_INDEX ();
-         record_unwind_protect (read_file_name_cleanup, current_buffer->directory);
-         current_buffer->directory = realdir;
-         for (comp = Qnil; CONSP (all); all = XCDR (all))
-           {
-             tem = call1 (Vread_file_name_predicate, XCAR (all));
-             if (!NILP (tem))
-               comp = Fcons (XCAR (all), comp);
-           }
-         unbind_to (count, Qnil);
-         UNGCPRO;
-       }
-      return Fnreverse (comp);
-    }
-
-  /* Only other case actually used is ACTION = lambda */
-#ifdef VMS
-  /* Supposedly this helps commands such as `cd' that read directory names,
-     but can someone explain how it helps them? -- RMS */
-  if (SCHARS (name) == 0)
-    return Qt;
-#endif /* VMS */
-  string = Fexpand_file_name (string, dir);
-  if (!NILP (Vread_file_name_predicate))
-    return call1 (Vread_file_name_predicate, string);
-  return Ffile_exists_p (string);
-}
 
 DEFUN ("next-read-file-uses-dialog-p", Fnext_read_file_uses_dialog_p,
        Snext_read_file_uses_dialog_p, 0, 0, 0,
@@ -6233,7 +5397,7 @@ The return value is only relevant for a call to `read-file-name' that happens
 before any other event (mouse or keypress) is handeled.  */)
   ()
 {
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
       && use_dialog_box
       && use_file_dialog
@@ -6243,214 +5407,22 @@ before any other event (mouse or keypress) is handeled.  */)
   return Qnil;
 }
 
-DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 6, 0,
-       doc: /* Read file name, prompting with PROMPT and completing in directory DIR.
-Value is not expanded---you must call `expand-file-name' yourself.
-Default name to DEFAULT-FILENAME if user exits the minibuffer with
-the same non-empty string that was inserted by this function.
- (If DEFAULT-FILENAME is omitted, the visited file name is used,
-  except that if INITIAL is specified, that combined with DIR is used.)
-If the user exits with an empty minibuffer, this function returns
-an empty string.  (This can only happen if the user erased the
-pre-inserted contents or if `insert-default-directory' is nil.)
-Fourth arg MUSTMATCH non-nil means require existing file's name.
- Non-nil and non-t means also require confirmation after completion.
-Fifth arg INITIAL specifies text to start with.
-If optional sixth arg PREDICATE is non-nil, possible completions and
-the resulting file name must satisfy (funcall PREDICATE NAME).
-DIR should be an absolute directory name.  It defaults to the value of
-`default-directory'.
-
-If this command was invoked with the mouse, use a file dialog box if
-`use-dialog-box' is non-nil, and the window system or X toolkit in use
-provides a file dialog box.
-
-See also `read-file-name-completion-ignore-case'
-and `read-file-name-function'.  */)
-     (prompt, dir, default_filename, mustmatch, initial, predicate)
+Lisp_Object
+Fread_file_name (prompt, dir, default_filename, mustmatch, initial, predicate)
      Lisp_Object prompt, dir, default_filename, mustmatch, initial, predicate;
 {
-  Lisp_Object val, insdef, tem;
   struct gcpro gcpro1, gcpro2;
-  register char *homedir;
-  Lisp_Object decoded_homedir;
-  int replace_in_history = 0;
-  int add_to_history = 0;
-  int count;
-
-  if (NILP (dir))
-    dir = current_buffer->directory;
-  if (NILP (Ffile_name_absolute_p (dir)))
-    dir = Fexpand_file_name (dir, Qnil);
-  if (NILP (default_filename))
-    default_filename
-      = (!NILP (initial)
-        ? Fexpand_file_name (initial, dir)
-        : current_buffer->filename);
-
-  /* If dir starts with user's homedir, change that to ~. */
-  homedir = (char *) egetenv ("HOME");
-#ifdef DOS_NT
-  /* homedir can be NULL in temacs, since Vglobal_environment is not
-     yet set up.  We shouldn't crash in that case.  */
-  if (homedir != 0)
-    {
-      homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
-      CORRECT_DIR_SEPS (homedir);
-    }
-#endif
-  if (homedir != 0)
-    decoded_homedir
-      = DECODE_FILE (make_unibyte_string (homedir, strlen (homedir)));
-  if (homedir != 0
-      && STRINGP (dir)
-      && !strncmp (SDATA (decoded_homedir), SDATA (dir),
-                  SBYTES (decoded_homedir))
-      && IS_DIRECTORY_SEP (SREF (dir, SBYTES (decoded_homedir))))
-    {
-      dir = Fsubstring (dir, make_number (SCHARS (decoded_homedir)), Qnil);
-      dir = concat2 (build_string ("~"), dir);
-    }
-  /* Likewise for default_filename.  */
-  if (homedir != 0
-      && STRINGP (default_filename)
-      && !strncmp (SDATA (decoded_homedir), SDATA (default_filename),
-                  SBYTES (decoded_homedir))
-      && IS_DIRECTORY_SEP (SREF (default_filename, SBYTES (decoded_homedir))))
-    {
-      default_filename
-       = Fsubstring (default_filename,
-                     make_number (SCHARS (decoded_homedir)), Qnil);
-      default_filename = concat2 (build_string ("~"), default_filename);
-    }
-  if (!NILP (default_filename))
-    {
-      CHECK_STRING (default_filename);
-      default_filename = double_dollars (default_filename);
-    }
-
-  if (insert_default_directory && STRINGP (dir))
-    {
-      insdef = dir;
-      if (!NILP (initial))
-       {
-         Lisp_Object args[2], pos;
-
-         args[0] = insdef;
-         args[1] = initial;
-         insdef = Fconcat (2, args);
-         pos = make_number (SCHARS (double_dollars (dir)));
-         insdef = Fcons (double_dollars (insdef), pos);
-       }
-      else
-       insdef = double_dollars (insdef);
-    }
-  else if (STRINGP (initial))
-    insdef = Fcons (double_dollars (initial), make_number (0));
-  else
-    insdef = Qnil;
-
-  if (!NILP (Vread_file_name_function))
-    {
-      Lisp_Object args[7];
-
-      GCPRO2 (insdef, default_filename);
-      args[0] = Vread_file_name_function;
-      args[1] = prompt;
-      args[2] = dir;
-      args[3] = default_filename;
-      args[4] = mustmatch;
-      args[5] = initial;
-      args[6] = predicate;
-      RETURN_UNGCPRO (Ffuncall (7, args));
-    }
-
-  count = SPECPDL_INDEX ();
-  specbind (Qcompletion_ignore_case,
-           read_file_name_completion_ignore_case ? Qt : Qnil);
-  specbind (intern ("minibuffer-completing-file-name"), Qt);
-  specbind (intern ("read-file-name-predicate"),
-           (NILP (predicate) ? Qfile_exists_p : predicate));
-
-  GCPRO2 (insdef, default_filename);
-
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
-  if (! NILP (Fnext_read_file_uses_dialog_p ()))
-    {
-      /* If DIR contains a file name, split it.  */
-      Lisp_Object file;
-      file = Ffile_name_nondirectory (dir);
-      if (SCHARS (file) && NILP (default_filename))
-       {
-         default_filename = file;
-         dir = Ffile_name_directory (dir);
-       }
-      if (!NILP(default_filename))
-        default_filename = Fexpand_file_name (default_filename, dir);
-      val = Fx_file_dialog (prompt, dir, default_filename, mustmatch,
-                            EQ (predicate, Qfile_directory_p) ? Qt : Qnil);
-      add_to_history = 1;
-    }
-  else
-#endif
-    val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
-                           dir, mustmatch, insdef,
-                           Qfile_name_history, default_filename, Qnil);
-
-  tem = Fsymbol_value (Qfile_name_history);
-  if (CONSP (tem) && EQ (XCAR (tem), val))
-    replace_in_history = 1;
-
-  /* If Fcompleting_read returned the inserted default string itself
-     (rather than a new string with the same contents),
-     it has to mean that the user typed RET with the minibuffer empty.
-     In that case, we really want to return ""
-     so that commands such as set-visited-file-name can distinguish.  */
-  if (EQ (val, default_filename))
-    {
-      /* In this case, Fcompleting_read has not added an element
-        to the history.  Maybe we should.  */
-      if (! replace_in_history)
-       add_to_history = 1;
-
-      val = empty_unibyte_string;
-    }
-
-  unbind_to (count, Qnil);
-  UNGCPRO;
-  if (NILP (val))
-    error ("No file name specified");
-
-  tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
-
-  if (!NILP (tem) && !NILP (default_filename))
-    val = default_filename;
-  val = Fsubstitute_in_file_name (val);
-
-  if (replace_in_history)
-    /* Replace what Fcompleting_read added to the history
-       with what we will actually return.  */
-    {
-       Lisp_Object val1 = double_dollars (val);
-       tem = Fsymbol_value (Qfile_name_history);
-       if (history_delete_duplicates)
-        XSETCDR (tem, Fdelete (val1, XCDR(tem)));
-       XSETCAR (tem, val1);
-    }
-  else if (add_to_history)
-    {
-      /* Add the value to the history--but not if it matches
-        the last value already there.  */
-      Lisp_Object val1 = double_dollars (val);
-      tem = Fsymbol_value (Qfile_name_history);
-      if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
-       {
-         if (history_delete_duplicates) tem = Fdelete (val1, tem);
-         Fset (Qfile_name_history, Fcons (val1, tem));
-       }
-    }
-
-  return val;
+  Lisp_Object args[7];
+
+  GCPRO1 (default_filename);
+  args[0] = intern ("read-file-name");
+  args[1] = prompt;
+  args[2] = dir;
+  args[3] = default_filename;
+  args[4] = mustmatch;
+  args[5] = initial;
+  args[6] = predicate;
+  RETURN_UNGCPRO (Ffuncall (7, args));
 }
 
 \f
@@ -6594,44 +5566,6 @@ of file names regardless of the current language environment.  */);
   Fput (Qfile_date_error, Qerror_message,
        build_string ("Cannot set file date"));
 
-  DEFVAR_LISP ("read-file-name-function", &Vread_file_name_function,
-              doc: /* If this is non-nil, `read-file-name' does its work by calling this function.  */);
-  Vread_file_name_function = Qnil;
-
-  DEFVAR_LISP ("read-file-name-predicate", &Vread_file_name_predicate,
-              doc: /* Current predicate used by `read-file-name-internal'.  */);
-  Vread_file_name_predicate = Qnil;
-
-  DEFVAR_BOOL ("read-file-name-completion-ignore-case", &read_file_name_completion_ignore_case,
-              doc: /* *Non-nil means when reading a file name completion ignores case.  */);
-#if defined VMS || defined DOS_NT || defined MAC_OS
-  read_file_name_completion_ignore_case = 1;
-#else
-  read_file_name_completion_ignore_case = 0;
-#endif
-
-  DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
-              doc: /* *Non-nil means when reading a filename start with default dir in minibuffer.
-If the initial minibuffer contents are non-empty, you can usually
-request a default filename by typing RETURN without editing.  For some
-commands, exiting with an empty minibuffer has a special meaning,
-such as making the current buffer visit no file in the case of
-`set-visited-file-name'.
-If this variable is non-nil, the minibuffer contents are always
-initially non-empty and typing RETURN without editing will fetch the
-default name, if one is provided.  Note however that this default name
-is not necessarily the name originally inserted in the minibuffer, if
-that is just the default directory.
-If this variable is nil, the minibuffer often starts out empty.  In
-that case you may have to explicitly fetch the next history element to
-request the default name.  */);
-  insert_default_directory = 1;
-
-  DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
-              doc: /* *Non-nil means write new files with record format `stmlf'.
-nil means use format `var'.  This variable is meaningful only on VMS.  */);
-  vms_stmlf_recfm = 0;
-
   DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
               doc: /* Directory separator character for built-in functions that return file names.
 The value is always ?/.  Don't use this variable, just use `/'.  */);
@@ -6715,6 +5649,11 @@ shortly after Emacs reads your `.emacs' file, if you have not yet given it
 a non-nil value.  */);
   Vauto_save_list_file_name = Qnil;
 
+  DEFVAR_LISP ("auto-save-visited-file-name", &Vauto_save_visited_file_name,
+              doc: /* Non-nil says auto-save a buffer in the file it is visiting, when practical.
+Normally auto-save files are written under other names.  */);
+  Vauto_save_visited_file_name = Qnil;
+
 #ifdef HAVE_FSYNC
   DEFVAR_BOOL ("write-region-inhibit-fsync", &write_region_inhibit_fsync,
               doc: /* *Non-nil means don't call fsync in `write-region'.
@@ -6723,6 +5662,14 @@ A non-nil value may result in data loss!  */);
   write_region_inhibit_fsync = 0;
 #endif
 
+  DEFVAR_BOOL ("delete-by-moving-to-trash", &delete_by_moving_to_trash,
+               doc: /* Specifies whether to use the system's trash can.
+When non-nil, the function `move-file-to-trash' will be used by
+`delete-file' and `delete-directory'.  */);
+  delete_by_moving_to_trash = 0;
+  Qmove_file_to_trash = intern ("move-file-to-trash");
+  staticpro (&Qmove_file_to_trash);
+
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
@@ -6738,15 +5685,7 @@ A non-nil value may result in data loss!  */);
   defsubr (&Sdelete_file);
   defsubr (&Srename_file);
   defsubr (&Sadd_name_to_file);
-#ifdef S_IFLNK
   defsubr (&Smake_symbolic_link);
-#endif /* S_IFLNK */
-#ifdef VMS
-  defsubr (&Sdefine_logical_name);
-#endif /* VMS */
-#ifdef HPUX_NET
-  defsubr (&Ssysnetunam);
-#endif /* HPUX_NET */
   defsubr (&Sfile_name_absolute_p);
   defsubr (&Sfile_exists_p);
   defsubr (&Sfile_executable_p);
@@ -6775,8 +5714,6 @@ A non-nil value may result in data loss!  */);
   defsubr (&Sclear_buffer_auto_save_failure);
   defsubr (&Srecent_auto_save_p);
 
-  defsubr (&Sread_file_name_internal);
-  defsubr (&Sread_file_name);
   defsubr (&Snext_read_file_uses_dialog_p);
 
 #ifdef HAVE_SYNC