]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
* macterm.c (mac_check_for_quit_char): Don't check more often than
[gnu-emacs] / src / fileio.c
index 08764855a7ecf2ceefd6601fb2d33b818d5050c8..29367875ac4346c76ddddeab0b69d05d03362924 100644 (file)
@@ -19,11 +19,9 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-#define _GNU_SOURCE            /* for euidaccess */
-
 #include <config.h>
 
-#if defined (USG5) || defined (BSD_SYSTEM) || defined (GNU_LINUX)
+#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
 
@@ -74,16 +72,6 @@ extern int errno;
 #include <sys/time.h>
 #endif
 
-#ifndef USG
-#ifndef VMS
-#ifndef BSD4_1
-#ifndef WINDOWSNT
-#define HAVE_FSYNC
-#endif
-#endif
-#endif
-#endif
-
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
@@ -189,6 +177,10 @@ Lisp_Object Vset_auto_coding_function;
 /* Functions to be called to process text properties in inserted file.  */
 Lisp_Object Vafter_insert_file_functions;
 
+/* Lisp function for setting buffer-file-coding-system and the
+   multibyteness of the current buffer after inserting a file.  */
+Lisp_Object Qafter_insert_file_set_coding;
+
 /* Functions to be called to create text property annotations for file.  */
 Lisp_Object Vwrite_region_annotate_functions;
 
@@ -200,7 +192,7 @@ Lisp_Object Vwrite_region_annotations_so_far;
 Lisp_Object Vauto_save_list_file_name;
 
 /* Function to call to read a file name.  */
-Lisp_Object Vread_file_name_function; 
+Lisp_Object Vread_file_name_function;
 
 /* Current predicate used by read_file_name_internal.  */
 Lisp_Object Vread_file_name_predicate;
@@ -250,7 +242,7 @@ static int e_write P_ ((int, Lisp_Object, int, int, struct coding_system *));
 \f
 void
 report_file_error (string, data)
-     char *string;
+     const char *string;
      Lisp_Object data;
 {
   Lisp_Object errstring;
@@ -269,8 +261,8 @@ report_file_error (string, data)
       default:
        /* System error messages are capitalized.  Downcase the initial
           unless it is followed by a slash.  */
-       if (XSTRING (errstring)->data[1] != '/')
-         XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
+       if (SREF (errstring, 1) != '/')
+         SSET (errstring, 0, DOWNCASE (SREF (errstring, 0)));
 
        Fsignal (Qfile_error,
                 Fcons (build_string (string), Fcons (errstring, data)));
@@ -393,8 +385,12 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.  */)
      (filename)
      Lisp_Object filename;
 {
+#ifndef DOS_NT
+  register const unsigned char *beg;
+#else
   register unsigned char *beg;
-  register unsigned char *p;
+#endif
+  register const unsigned char *p;
   Lisp_Object handler;
 
   CHECK_STRING (filename);
@@ -408,11 +404,11 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.  */)
 #ifdef FILE_SYSTEM_CASE
   filename = FILE_SYSTEM_CASE (filename);
 #endif
-  beg = XSTRING (filename)->data;
+  beg = SDATA (filename);
 #ifdef DOS_NT
   beg = strcpy (alloca (strlen (beg) + 1), beg);
 #endif
-  p = beg + STRING_BYTES (XSTRING (filename));
+  p = beg + SBYTES (filename);
 
   while (p != beg && !IS_DIRECTORY_SEP (p[-1])
 #ifdef VMS
@@ -455,9 +451,7 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.  */)
   CORRECT_DIR_SEPS (beg);
 #endif /* DOS_NT */
 
-  if (STRING_MULTIBYTE (filename))
-    return make_string (beg, p - beg);
-  return make_unibyte_string (beg, p - beg);
+  return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
 }
 
 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,
@@ -469,7 +463,7 @@ or the entire name if it contains no slash.  */)
      (filename)
      Lisp_Object filename;
 {
-  register unsigned char *beg, *p, *end;
+  register const unsigned char *beg, *p, *end;
   Lisp_Object handler;
 
   CHECK_STRING (filename);
@@ -480,8 +474,8 @@ or the entire name if it contains no slash.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_name_nondirectory, filename);
 
-  beg = XSTRING (filename)->data;
-  end = p = beg + STRING_BYTES (XSTRING (filename));
+  beg = SDATA (filename);
+  end = p = beg + SBYTES (filename);
 
   while (p != beg && !IS_DIRECTORY_SEP (p[-1])
 #ifdef VMS
@@ -496,9 +490,7 @@ or the entire name if it contains no slash.  */)
         )
     p--;
 
-  if (STRING_MULTIBYTE (filename))
-    return make_string (p, end - p);
-  return make_unibyte_string (p, end - p);
+  return make_specified_string (p, -1, end - p, STRING_MULTIBYTE (filename));
 }
 
 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory,
@@ -602,7 +594,8 @@ file_name_as_directory (out, in)
   /* For Unix syntax, Append a slash if necessary */
   if (!IS_DIRECTORY_SEP (out[size]))
     {
-      out[size + 1] = DIRECTORY_SEP;
+      /* Cannot use DIRECTORY_SEP, which could have any value */
+      out[size + 1] = '/';
       out[size + 2] = '\0';
     }
 #ifdef DOS_NT
@@ -614,7 +607,7 @@ file_name_as_directory (out, in)
 
 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
        Sfile_name_as_directory, 1, 1, 0,
-       doc: /* Return a string representing file FILENAME interpreted as a directory.
+       doc: /* Return a string representing the file name FILE interpreted as a 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.
 The result can be used as the value of `default-directory'
@@ -637,8 +630,10 @@ On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_name_as_directory, file);
 
-  buf = (char *) alloca (STRING_BYTES (XSTRING (file)) + 10);
-  return build_string (file_name_as_directory (buf, XSTRING (file)->data));
+  buf = (char *) alloca (SBYTES (file) + 10);
+  file_name_as_directory (buf, SDATA (file));
+  return make_specified_string (buf, -1, strlen (buf),
+                               STRING_MULTIBYTE (file));
 }
 \f
 /*
@@ -833,12 +828,13 @@ it returns a file name such as \"[X]Y.DIR.1\".  */)
   /* 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 (STRING_BYTES (XSTRING (directory)) + 20 + 255);
+  buf = (char *) alloca (SBYTES (directory) + 20 + 255);
 #else
-  buf = (char *) alloca (STRING_BYTES (XSTRING (directory)) + 20);
+  buf = (char *) alloca (SBYTES (directory) + 20);
 #endif
-  directory_file_name (XSTRING (directory)->data, buf);
-  return build_string (buf);
+  directory_file_name (SDATA (directory), buf);
+  return make_specified_string (buf, -1, strlen (buf),
+                               STRING_MULTIBYTE (directory));
 }
 
 static char make_temp_name_tbl[64] =
@@ -856,13 +852,13 @@ static char make_temp_name_tbl[64] =
 static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
 
 /* Value is a temporary file name starting with PREFIX, a string.
-   
+
    The Emacs process number forms part of the result, so there is
    no danger of generating a name being used by another process.
    In addition, this function makes an attempt to choose a name
    which has no existing file.  To make this work, PREFIX should be
    an absolute file name.
-   
+
    BASE64_P non-zero means add the pid as 3 characters in base64
    encoding.  In this case, 6 characters will be added to PREFIX to
    form the file name.  Otherwise, if Emacs is running on a system
@@ -882,7 +878,7 @@ make_temp_name (prefix, base64_p)
   unsigned char *p, *data;
   char pidbuf[20];
   int pidlen;
-     
+
   CHECK_STRING (prefix);
 
   /* VAL is created by adding 6 characters to PREFIX.  The first
@@ -911,11 +907,11 @@ make_temp_name (prefix, base64_p)
       pidlen = 3;
 #endif
     }
-  
-  len = XSTRING (prefix)->size;
+
+  len = SCHARS (prefix);
   val = make_uninit_string (len + 3 + pidlen);
-  data = XSTRING (val)->data;
-  bcopy(XSTRING (prefix)->data, data, len);
+  data = SDATA (val);
+  bcopy(SDATA (prefix), data, len);
   p = data + len;
 
   bcopy (pidbuf, p, pidlen);
@@ -970,7 +966,7 @@ make_temp_name (prefix, base64_p)
     }
 
   error ("Cannot create temporary name for prefix `%s'",
-        XSTRING (prefix)->data);
+        SDATA (prefix));
   return Qnil;
 }
 
@@ -1034,7 +1030,7 @@ See also the function `substitute-in-file-name'.  */)
   int is_escaped = 0;
 #endif /* DOS_NT */
   int length;
-  Lisp_Object handler;
+  Lisp_Object handler, result;
 
   CHECK_STRING (name);
 
@@ -1073,7 +1069,7 @@ See also the function `substitute-in-file-name'.  */)
        return call3 (handler, Qexpand_file_name, name, default_directory);
     }
 
-  o = XSTRING (default_directory)->data;
+  o = SDATA (default_directory);
 
   /* Make sure DEFAULT_DIRECTORY is properly expanded.
      It would be better to do this down below where we actually use
@@ -1118,7 +1114,7 @@ See also the function `substitute-in-file-name'.  */)
   name = FILE_SYSTEM_CASE (name);
 #endif
 
-  nm = XSTRING (name)->data;
+  nm = SDATA (name);
 
 #ifdef DOS_NT
   /* We will force directory separators to be either all \ or /, so make
@@ -1202,7 +1198,7 @@ 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;
@@ -1282,7 +1278,11 @@ See also the function `substitute-in-file-name'.  */)
        {
 #ifdef VMS
          if (index (nm, '/'))
-           return build_string (sys_translate_unix (nm));
+           {
+             nm = sys_translate_unix (nm);
+             return make_specified_string (nm, -1, strlen (nm),
+                                           STRING_MULTIBYTE (name));
+           }
 #endif /* VMS */
 #ifdef DOS_NT
          /* Make sure directories are all separated with / or \ as
@@ -1292,23 +1292,28 @@ See also the function `substitute-in-file-name'.  */)
 #ifdef WINDOWSNT
          if (IS_DIRECTORY_SEP (nm[1]))
            {
-             if (strcmp (nm, XSTRING (name)->data) != 0)
-               name = build_string (nm);
+             if (strcmp (nm, SDATA (name)) != 0)
+               name = make_specified_string (nm, -1, strlen (nm),
+                                             STRING_MULTIBYTE (name));
            }
          else
 #endif
          /* drive must be set, so this is okay */
-         if (strcmp (nm - 2, XSTRING (name)->data) != 0)
+         if (strcmp (nm - 2, SDATA (name)) != 0)
            {
-             name = make_string (nm - 2, p - nm + 2);
-             XSTRING (name)->data[0] = DRIVE_LETTER (drive);
-             XSTRING (name)->data[1] = ':';
+             char temp[] = " :";
+
+             name = make_specified_string (nm, -1, p - nm,
+                                           STRING_MULTIBYTE (name));
+             temp[0] = DRIVE_LETTER (drive);
+             name = concat2 (build_string (temp), name);
            }
          return name;
 #else /* not DOS_NT */
-         if (nm == XSTRING (name)->data)
+         if (nm == SDATA (name))
            return name;
-         return build_string (nm);
+         return make_specified_string (nm, -1, strlen (nm),
+                                       STRING_MULTIBYTE (name));
 #endif /* not DOS_NT */
        }
     }
@@ -1419,7 +1424,7 @@ See also the function `substitute-in-file-name'.  */)
 #endif
       && !newdir)
     {
-      newdir = XSTRING (default_directory)->data;
+      newdir = SDATA (default_directory);
 #ifdef DOS_NT
       /* Note if special escape prefix is present, but remove for now.  */
       if (newdir[0] == '/' && newdir[1] == ':')
@@ -1545,7 +1550,7 @@ See also the function `substitute-in-file-name'.  */)
             absolute directory in nm produces "//", which will then be
             incorrectly treated as a network share.  Ignore newdir in
             this case (keeping the drive letter).  */
-         if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) 
+         if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
                && newdir[1] == '\0'))
 #endif
            strcpy (target, newdir);
@@ -1677,7 +1682,19 @@ See also the function `substitute-in-file-name'.  */)
   CORRECT_DIR_SEPS (target);
 #endif /* DOS_NT */
 
-  return make_string (target, o - target);
+  result = make_specified_string (target, -1, o - target,
+                                  STRING_MULTIBYTE (name));
+
+  /* Again look to see if the file name has special constructs in it
+     and perhaps call the corresponding file handler.  This is needed
+     for filenames such as "/foo/../user@host:/bar/../baz".  Expanding
+     the ".." component gives us "/user@host:/bar/../baz" which needs
+     to be expanded again. */
+  handler = Ffind_file_name_handler (result, Qexpand_file_name);
+  if (!NILP (handler))
+    return call3 (handler, Qexpand_file_name, result, default_directory);
+
+  return result;
 }
 
 #if 0
@@ -1726,7 +1743,7 @@ See also the function `substitute-in-file-name'.")
   name = Fupcase (name);
 #endif
 
-  nm = XSTRING (name)->data;
+  nm = SDATA (name);
 
   /* If nm is absolute, flush ...// and detect /./ and /../.
      If no /./ or /../ we can return right away.  */
@@ -1835,7 +1852,7 @@ See also the function `substitute-in-file-name'.")
          if (index (nm, '/'))
            return build_string (sys_translate_unix (nm));
 #endif /* VMS */
-         if (nm == XSTRING (name)->data)
+         if (nm == SDATA (name))
            return name;
          return build_string (nm);
        }
@@ -1896,7 +1913,7 @@ See also the function `substitute-in-file-name'.")
       if (NILP (defalt))
        defalt = current_buffer->directory;
       CHECK_STRING (defalt);
-      newdir = XSTRING (defalt)->data;
+      newdir = SDATA (defalt);
     }
 
   /* Now concatenate the directory and name to new space in the stack frame */
@@ -2046,26 +2063,26 @@ duplicates what `expand-file-name' does.  */)
   if (!NILP (handler))
     return call2 (handler, Qsubstitute_in_file_name, filename);
 
-  nm = XSTRING (filename)->data;
+  nm = SDATA (filename);
 #ifdef DOS_NT
   nm = strcpy (alloca (strlen (nm) + 1), nm);
   CORRECT_DIR_SEPS (nm);
-  substituted = (strcmp (nm, XSTRING (filename)->data) != 0);
+  substituted = (strcmp (nm, SDATA (filename)) != 0);
 #endif
-  endp = nm + STRING_BYTES (XSTRING (filename));
+  endp = nm + SBYTES (filename);
 
   /* If /~ or // appears, discard everything through first slash.  */
 
   for (p = nm; p != endp; p++)
     {
       if ((p[0] == '~'
-#if defined (APOLLO) || defined (WINDOWSNT)
-          /* // at start of file name is meaningful in Apollo and
-             WindowsNT systems.  */
+#if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN)
+          /* // at start of file name is meaningful in Apollo,
+             WindowsNT and Cygwin systems.  */
           || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
-#else /* not (APOLLO || WINDOWSNT) */
+#else /* not (APOLLO || WINDOWSNT || CYGWIN) */
           || IS_DIRECTORY_SEP (p[0])
-#endif /* not (APOLLO || WINDOWSNT) */
+#endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
           )
          && p != nm
          && (0
@@ -2108,7 +2125,8 @@ duplicates what `expand-file-name' does.  */)
     }
 
 #ifdef VMS
-  return build_string (nm);
+  return make_specified_string (nm, -1, strlen (nm),
+                               STRING_MULTIBYTE (filename));
 #else
 
   /* See if any variables are substituted into the string
@@ -2168,7 +2186,7 @@ duplicates what `expand-file-name' does.  */)
 
   /* If substitution required, recopy the string and do it */
   /* Make space in stack frame for the new copy */
-  xnm = (unsigned char *) alloca (STRING_BYTES (XSTRING (filename)) + total + 1);
+  xnm = (unsigned char *) alloca (SBYTES (filename) + total + 1);
   x = xnm;
 
   /* Copy the rest of the name through, replacing $ constructs with values */
@@ -2237,11 +2255,11 @@ duplicates what `expand-file-name' does.  */)
 
   for (p = xnm; p != x; p++)
     if ((p[0] == '~'
-#if defined (APOLLO) || defined (WINDOWSNT)
+#if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN)
         || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
-#else /* not (APOLLO || WINDOWSNT) */
+#else /* not (APOLLO || WINDOWSNT || CYGWIN) */
         || IS_DIRECTORY_SEP (p[0])
-#endif /* not (APOLLO || WINDOWSNT) */
+#endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
         )
        && p != xnm && IS_DIRECTORY_SEP (p[-1]))
       xnm = p;
@@ -2251,9 +2269,7 @@ duplicates what `expand-file-name' does.  */)
       xnm = p;
 #endif
 
-  if (STRING_MULTIBYTE (filename))
-    return make_string (xnm, x - xnm);
-  return make_unibyte_string (xnm, x - xnm);
+  return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename));
 
  badsubst:
   error ("Bad format environment-variable substitution");
@@ -2279,16 +2295,16 @@ expand_and_dir_to_file (filename, defdir)
   absname = Fexpand_file_name (filename, defdir);
 #ifdef VMS
   {
-    register int c = XSTRING (absname)->data[STRING_BYTES (XSTRING (absname)) - 1];
+    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 (XSTRING (absname)->size > 1
-      && IS_DIRECTORY_SEP (XSTRING (absname)->data[STRING_BYTES (XSTRING (absname)) - 1])
-      && !IS_DEVICE_SEP (XSTRING (absname)->data[STRING_BYTES (XSTRING (absname))-2]))
+  if (SCHARS (absname) > 1
+      && IS_DIRECTORY_SEP (SREF (absname, SBYTES (absname) - 1))
+      && !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
@@ -2323,15 +2339,15 @@ barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
 
   /* stat is a good way to tell whether the file exists,
      regardless of what access permissions it has.  */
-  if (stat (XSTRING (encoded_filename)->data, &statbuf) >= 0)
+  if (stat (SDATA (encoded_filename), &statbuf) >= 0)
     {
       if (! interactive)
        Fsignal (Qfile_already_exists,
                 Fcons (build_string ("File already exists"),
                        Fcons (absname, Qnil)));
       GCPRO1 (absname);
-      tem = format1 ("File %s already exists; %s anyway? ",
-                    XSTRING (absname)->data, querystring);
+      tem = format2 ("File %s already exists; %s anyway? ",
+                    absname, build_string (querystring));
       if (quick)
        tem = Fy_or_n_p (tem);
       else
@@ -2371,7 +2387,7 @@ A prefix arg makes KEEP-TIME non-nil.  */)
   struct stat st, out_st;
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   int input_file_statable_p;
   Lisp_Object encoded_file, encoded_newname;
 
@@ -2404,14 +2420,15 @@ A prefix arg makes KEEP-TIME non-nil.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (encoded_newname, "copy to it",
                                  INTEGERP (ok_if_already_exists), &out_st, 0);
-  else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
+  else if (stat (SDATA (encoded_newname), &out_st) < 0)
     out_st.st_mode = 0;
 
 #ifdef WINDOWSNT
-  if (!CopyFile (XSTRING (encoded_file)->data,
-                XSTRING (encoded_newname)->data, 
+  if (!CopyFile (SDATA (encoded_file),
+                SDATA (encoded_newname),
                 FALSE))
     report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil)));
+  /* CopyFile retains the timestamp by default.  */
   else if (NILP (keep_time))
     {
       EMACS_TIME now;
@@ -2419,7 +2436,7 @@ A prefix arg makes KEEP-TIME non-nil.  */)
       char * filename;
 
       EMACS_GET_TIME (now);
-      filename = XSTRING (encoded_newname)->data;
+      filename = SDATA (encoded_newname);
 
       /* Ensure file is writable while its modified time is set.  */
       attributes = GetFileAttributes (filename);
@@ -2436,7 +2453,10 @@ A prefix arg makes KEEP-TIME non-nil.  */)
       SetFileAttributes (filename, attributes);
     }
 #else /* not WINDOWSNT */
-  ifd = emacs_open (XSTRING (encoded_file)->data, O_RDONLY, 0);
+  immediate_quit = 1;
+  ifd = emacs_open (SDATA (encoded_file), O_RDONLY, 0);
+  immediate_quit = 0;
+
   if (ifd < 0)
     report_file_error ("Opening input file", Fcons (file, Qnil));
 
@@ -2472,13 +2492,13 @@ A prefix arg makes KEEP-TIME non-nil.  */)
 
 #ifdef VMS
   /* Create the copy file with the same record format as the input file */
-  ofd = sys_creat (XSTRING (encoded_newname)->data, 0666, ifd);
+  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 = creat (XSTRING (encoded_newname)->data, S_IREAD | S_IWRITE);
+  ofd = creat (SDATA (encoded_newname), S_IREAD | S_IWRITE);
 #else /* not MSDOS */
-  ofd = creat (XSTRING (encoded_newname)->data, 0666);
+  ofd = creat (SDATA (encoded_newname), 0666);
 #endif /* not MSDOS */
 #endif /* VMS */
   if (ofd < 0)
@@ -2504,14 +2524,14 @@ A prefix arg makes KEEP-TIME non-nil.  */)
          EMACS_TIME atime, mtime;
          EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
          EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
-         if (set_file_times (XSTRING (encoded_newname)->data,
+         if (set_file_times (SDATA (encoded_newname),
                              atime, mtime))
            Fsignal (Qfile_date_error,
                     Fcons (build_string ("Cannot set file date"),
                            Fcons (newname, Qnil)));
        }
 #ifndef MSDOS
-      chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
+      chmod (SDATA (encoded_newname), st.st_mode & 07777);
 #else /* MSDOS */
 #if defined (__DJGPP__) && __DJGPP__ > 1
       /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
@@ -2519,7 +2539,7 @@ A prefix arg makes KEEP-TIME non-nil.  */)
          get only the READ bit, which will make the copied file read-only,
          so it's better not to chmod at all.  */
       if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
-       chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
+       chmod (SDATA (encoded_newname), st.st_mode & 07777);
 #endif /* DJGPP version 2 or newer */
 #endif /* MSDOS */
     }
@@ -2540,7 +2560,7 @@ DEFUN ("make-directory-internal", Fmake_directory_internal,
      (directory)
      Lisp_Object directory;
 {
-  unsigned char *dir;
+  const unsigned char *dir;
   Lisp_Object handler;
   Lisp_Object encoded_dir;
 
@@ -2553,7 +2573,7 @@ DEFUN ("make-directory-internal", Fmake_directory_internal,
 
   encoded_dir = ENCODE_FILE (directory);
 
-  dir = XSTRING (encoded_dir)->data;
+  dir = SDATA (encoded_dir);
 
 #ifdef WINDOWSNT
   if (mkdir (dir) != 0)
@@ -2566,11 +2586,11 @@ DEFUN ("make-directory-internal", Fmake_directory_internal,
 }
 
 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
-       doc: /* Delete the directory named DIRECTORY.  */)
+       doc: /* Delete the directory named DIRECTORY.  Does not follow symlinks.  */)
      (directory)
      Lisp_Object directory;
 {
-  unsigned char *dir;
+  const unsigned char *dir;
   Lisp_Object handler;
   Lisp_Object encoded_dir;
 
@@ -2583,7 +2603,7 @@ DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete
 
   encoded_dir = ENCODE_FILE (directory);
 
-  dir = XSTRING (encoded_dir)->data;
+  dir = SDATA (encoded_dir);
 
   if (rmdir (dir) != 0)
     report_file_error ("Removing directory", Flist (1, &directory));
@@ -2592,15 +2612,21 @@ DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete
 }
 
 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
-       doc: /* Delete file named FILENAME.
+       doc: /* Delete file named FILENAME.  If it is a symlink, remove the symlink.
 If file has multiple names, it continues to exist with the other names.  */)
      (filename)
      Lisp_Object filename;
 {
   Lisp_Object handler;
   Lisp_Object encoded_file;
+  struct gcpro gcpro1;
 
-  CHECK_STRING (filename);
+  GCPRO1 (filename);
+  if (!NILP (Ffile_directory_p (filename)))
+    Fsignal (Qfile_error,
+            Fcons (build_string ("Removing old name: is a directory"),
+                   Fcons (filename, Qnil)));
+  UNGCPRO;
   filename = Fexpand_file_name (filename, Qnil);
 
   handler = Ffind_file_name_handler (filename, Qdelete_file);
@@ -2609,7 +2635,7 @@ If file has multiple names, it continues to exist with the other names.  */)
 
   encoded_file = ENCODE_FILE (filename);
 
-  if (0 > unlink (XSTRING (encoded_file)->data))
+  if (0 > unlink (SDATA (encoded_file)))
     report_file_error ("Removing old name", Flist (1, &filename));
   return Qnil;
 }
@@ -2679,10 +2705,10 @@ This is what happens in interactive use with M-x.  */)
     barf_or_query_if_file_exists (encoded_newname, "rename to it",
                                  INTEGERP (ok_if_already_exists), 0, 0);
 #ifndef BSD4_1
-  if (0 > rename (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
+  if (0 > rename (SDATA (encoded_file), SDATA (encoded_newname)))
 #else
-  if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data)
-      || 0 > unlink (XSTRING (encoded_file)->data))
+  if (0 > link (SDATA (encoded_file), SDATA (encoded_newname))
+      || 0 > unlink (SDATA (encoded_file)))
 #endif
     {
       if (errno == EXDEV)
@@ -2754,8 +2780,8 @@ This is what happens in interactive use with M-x.  */)
     barf_or_query_if_file_exists (encoded_newname, "make it a new name",
                                  INTEGERP (ok_if_already_exists), 0, 0);
 
-  unlink (XSTRING (newname)->data);
-  if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
+  unlink (SDATA (newname));
+  if (0 > link (SDATA (encoded_file), SDATA (encoded_newname)))
     {
 #ifdef NO_ARG_ARRAY
       args[0] = file;
@@ -2795,7 +2821,7 @@ This happens for interactive use with M-x.  */)
   /* If the link target has a ~, we must expand it to get
      a truly valid file name.  Otherwise, do not expand;
      we want to permit links to relative file names.  */
-  if (XSTRING (filename)->data[0] == '~')
+  if (SREF (filename, 0) == '~')
     filename = Fexpand_file_name (filename, Qnil);
   linkname = Fexpand_file_name (linkname, Qnil);
 
@@ -2820,15 +2846,15 @@ This happens for interactive use with M-x.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (encoded_linkname, "make it a link",
                                  INTEGERP (ok_if_already_exists), 0, 0);
-  if (0 > symlink (XSTRING (encoded_filename)->data,
-                  XSTRING (encoded_linkname)->data))
+  if (0 > symlink (SDATA (encoded_filename),
+                  SDATA (encoded_linkname)))
     {
       /* If we didn't complain already, silently delete existing file.  */
       if (errno == EEXIST)
        {
-         unlink (XSTRING (encoded_linkname)->data);
-         if (0 <= symlink (XSTRING (encoded_filename)->data,
-                           XSTRING (encoded_linkname)->data))
+         unlink (SDATA (encoded_linkname));
+         if (0 <= symlink (SDATA (encoded_filename),
+                           SDATA (encoded_linkname)))
            {
              UNGCPRO;
              return Qnil;
@@ -2860,15 +2886,15 @@ If STRING is nil or a null string, the logical name NAME is deleted.  */)
 {
   CHECK_STRING (name);
   if (NILP (string))
-    delete_logical_name (XSTRING (name)->data);
+    delete_logical_name (SDATA (name));
   else
     {
       CHECK_STRING (string);
 
-      if (XSTRING (string)->size == 0)
-       delete_logical_name (XSTRING (name)->data);
+      if (SCHARS (string) == 0)
+       delete_logical_name (SDATA (name));
       else
-       define_logical_name (XSTRING (name)->data, XSTRING (string)->data);
+       define_logical_name (SDATA (name), SDATA (string));
     }
 
   return string;
@@ -2887,7 +2913,7 @@ DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
   CHECK_STRING (path);
   CHECK_STRING (login);
 
-  netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
+  netresult = netunam (SDATA (path), SDATA (login));
 
   if (netresult == -1)
     return Qnil;
@@ -2903,10 +2929,10 @@ On Unix, this is a name starting with a `/' or a `~'.  */)
      (filename)
      Lisp_Object filename;
 {
-  unsigned char *ptr;
+  const unsigned char *ptr;
 
   CHECK_STRING (filename);
-  ptr = XSTRING (filename)->data;
+  ptr = SDATA (filename);
   if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
 #ifdef VMS
 /* ??? This criterion is probably wrong for '<'.  */
@@ -3003,7 +3029,7 @@ See also `file-readable-p' and `file-attributes'.  */)
 
   absname = ENCODE_FILE (absname);
 
-  return (stat (XSTRING (absname)->data, &statbuf) >= 0) ? Qt : Qnil;
+  return (stat (SDATA (absname), &statbuf) >= 0) ? Qt : Qnil;
 }
 
 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -3026,7 +3052,7 @@ For a directory, this means you can access files in that directory.  */)
 
   absname = ENCODE_FILE (absname);
 
-  return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
+  return (check_executable (SDATA (absname)) ? Qt : Qnil);
 }
 
 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
@@ -3055,7 +3081,7 @@ See also `file-exists-p' and `file-attributes'.  */)
 #if defined(DOS_NT) || defined(macintosh)
   /* Under MS-DOS, Windows, and Macintosh, open does not work for
      directories.  */
-  if (access (XSTRING (absname)->data, 0) == 0)
+  if (access (SDATA (absname), 0) == 0)
     return Qt;
   return Qnil;
 #else /* not DOS_NT and not macintosh */
@@ -3064,13 +3090,13 @@ See also `file-exists-p' and `file-attributes'.  */)
   /* Opening a fifo without O_NONBLOCK can wait.
      We don't want to wait.  But we don't want to mess wth O_NONBLOCK
      except in the case of a fifo, on a system which handles it.  */
-  desc = stat (XSTRING (absname)->data, &statbuf);
+  desc = stat (SDATA (absname), &statbuf);
   if (desc < 0)
     return Qnil;
   if (S_ISFIFO (statbuf.st_mode))
     flags |= O_NONBLOCK;
 #endif
-  desc = emacs_open (XSTRING (absname)->data, flags, 0);
+  desc = emacs_open (SDATA (absname), flags, 0);
   if (desc < 0)
     return Qnil;
   emacs_close (desc);
@@ -3099,8 +3125,8 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
     return call2 (handler, Qfile_writable_p, absname);
 
   encoded = ENCODE_FILE (absname);
-  if (stat (XSTRING (encoded)->data, &statbuf) >= 0)
-    return (check_writable (XSTRING (encoded)->data)
+  if (stat (SDATA (encoded), &statbuf) >= 0)
+    return (check_writable (SDATA (encoded))
            ? Qt : Qnil);
 
   dir = Ffile_name_directory (absname);
@@ -3118,11 +3144,11 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
   /* The read-only attribute of the parent directory doesn't affect
      whether a file or directory can be created within it.  Some day we
      should check ACLs though, which do affect this.  */
-  if (stat (XSTRING (dir)->data, &statbuf) < 0)
+  if (stat (SDATA (dir), &statbuf) < 0)
     return Qnil;
   return (statbuf.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
 #else
-  return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
+  return (check_writable (!NILP (dir) ? (char *) SDATA (dir) : "")
          ? Qt : Qnil);
 #endif
 }
@@ -3150,9 +3176,9 @@ If there is no error, we return nil.  */)
 
   encoded_filename = ENCODE_FILE (absname);
 
-  fd = emacs_open (XSTRING (encoded_filename)->data, O_RDONLY, 0);
+  fd = emacs_open (SDATA (encoded_filename), O_RDONLY, 0);
   if (fd < 0)
-    report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
+    report_file_error (SDATA (string), Fcons (filename, Qnil));
   emacs_close (fd);
 
   return Qnil;
@@ -3160,7 +3186,7 @@ If there is no error, we return nil.  */)
 \f
 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
        doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
-The value is the name of the file to which it is linked.
+The value is the link target, as a string.
 Otherwise returns nil.  */)
      (filename)
      Lisp_Object filename;
@@ -3190,9 +3216,9 @@ Otherwise returns nil.  */)
       bufsize *= 2;
       buf = (char *) xrealloc (buf, bufsize);
       bzero (buf, bufsize);
-      
+
       errno = 0;
-      valsize = readlink (XSTRING (filename)->data, buf, bufsize);
+      valsize = readlink (SDATA (filename), buf, bufsize);
       if (valsize == -1)
        {
 #ifdef ERANGE
@@ -3208,7 +3234,7 @@ Otherwise returns nil.  */)
        }
     }
   while (valsize >= bufsize);
-  
+
   val = make_string (buf, valsize);
   if (buf[0] == '/' && index (buf, ':'))
     val = concat2 (build_string ("/:"), val);
@@ -3241,7 +3267,7 @@ See `file-symlink-p' to distinguish symlinks.  */)
 
   absname = ENCODE_FILE (absname);
 
-  if (stat (XSTRING (absname)->data, &st) < 0)
+  if (stat (SDATA (absname), &st) < 0)
     return Qnil;
   return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
 }
@@ -3267,12 +3293,6 @@ searchable directory.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_accessible_directory_p, filename);
 
-  /* It's an unlikely combination, but yes we really do need to gcpro:
-     Suppose that file-accessible-directory-p has no handler, but
-     file-directory-p does have a handler; this handler causes a GC which
-     relocates the string in `filename'; and finally file-directory-p
-     returns non-nil.  Then we would end up passing a garbaged string
-     to file-executable-p.  */
   GCPRO1 (filename);
   tem = (NILP (Ffile_directory_p (filename))
         || NILP (Ffile_executable_p (filename)));
@@ -3307,7 +3327,7 @@ This is the sort of file that holds an ordinary stream of data bytes.  */)
 
     /* Tell stat to use expensive method to get accurate info.  */
     Vw32_get_true_file_attributes = Qt;
-    result = stat (XSTRING (absname)->data, &st);
+    result = stat (SDATA (absname), &st);
     Vw32_get_true_file_attributes = tem;
 
     if (result < 0)
@@ -3315,7 +3335,7 @@ This is the sort of file that holds an ordinary stream of data bytes.  */)
     return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
   }
 #else
-  if (stat (XSTRING (absname)->data, &st) < 0)
+  if (stat (SDATA (absname), &st) < 0)
     return Qnil;
   return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
 #endif
@@ -3340,10 +3360,10 @@ DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
 
   absname = ENCODE_FILE (absname);
 
-  if (stat (XSTRING (absname)->data, &st) < 0)
+  if (stat (SDATA (absname), &st) < 0)
     return Qnil;
 #if defined (MSDOS) && __DJGPP__ < 2
-  if (check_executable (XSTRING (absname)->data))
+  if (check_executable (SDATA (absname)))
     st.st_mode |= S_IEXEC;
 #endif /* MSDOS && __DJGPP__ < 2 */
 
@@ -3370,7 +3390,7 @@ Only the 12 low bits of MODE are used.  */)
 
   encoded_absname = ENCODE_FILE (absname);
 
-  if (chmod (XSTRING (encoded_absname)->data, XINT (mode)) < 0)
+  if (chmod (SDATA (encoded_absname), XINT (mode)) < 0)
     report_file_error ("Doing chmod", Fcons (absname, Qnil));
 
   return Qnil;
@@ -3456,12 +3476,12 @@ otherwise, if FILE2 does not exist, the answer is t.  */)
   absname2 = ENCODE_FILE (absname2);
   UNGCPRO;
 
-  if (stat (XSTRING (absname1)->data, &st) < 0)
+  if (stat (SDATA (absname1), &st) < 0)
     return Qnil;
 
   mtime1 = st.st_mtime;
 
-  if (stat (XSTRING (absname2)->data, &st) < 0)
+  if (stat (SDATA (absname2), &st) < 0)
     return Qt;
 
   return (mtime1 > st.st_mtime) ? Qt : Qnil;
@@ -3534,7 +3554,7 @@ static Lisp_Object
 read_non_regular ()
 {
   int nbytes;
-  
+
   immediate_quit = 1;
   QUIT;
   nbytes = emacs_read (non_regular_fd,
@@ -3558,7 +3578,7 @@ read_non_regular_quit ()
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
        1, 5, 0,
        doc: /* Insert contents of file FILENAME after point.
-Returns list of absolute file name and number of bytes inserted.
+Returns list of absolute file name and number of characters inserted.
 If second argument VISIT is non-nil, the buffer's visited filename
 and last save file modtime are set, and it is marked unmodified.
 If visiting and the file does not exist, visiting is completed
@@ -3588,7 +3608,7 @@ actually used.  */)
   int inserted = 0;
   register int how_much;
   register int unprocessed;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object handler, val, insval, orig_filename;
   Lisp_Object p;
@@ -3640,15 +3660,15 @@ actually used.  */)
 
     /* Tell stat to use expensive method to get accurate info.  */
     Vw32_get_true_file_attributes = Qt;
-    total = stat (XSTRING (filename)->data, &st);
+    total = stat (SDATA (filename), &st);
     Vw32_get_true_file_attributes = tem;
   }
   if (total < 0)
 #else
 #ifndef APOLLO
-  if (stat (XSTRING (filename)->data, &st) < 0)
+  if (stat (SDATA (filename), &st) < 0)
 #else
-  if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0
+  if ((fd = emacs_open (SDATA (filename), O_RDONLY, 0)) < 0
       || fstat (fd, &st) < 0)
 #endif /* not APOLLO */
 #endif /* WINDOWSNT */
@@ -3683,7 +3703,7 @@ actually used.  */)
 #endif
 
   if (fd < 0)
-    if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0)
+    if ((fd = emacs_open (SDATA (filename), O_RDONLY, 0)) < 0)
       goto badopen;
 
   /* Replacement should preserve point as it preserves markers.  */
@@ -3693,8 +3713,11 @@ 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.  */
   if (! not_regular && st.st_size < 0)
-    error ("File size is negative");
+    error ("Maximum buffer size exceeded");
 
   /* Prevent redisplay optimizations.  */
   current_buffer->clip_changed = 1;
@@ -3779,7 +3802,7 @@ actually used.  */)
 
              if (nread < 0)
                error ("IO error reading %s: %s",
-                      XSTRING (orig_filename)->data, emacs_strerror (errno));
+                      SDATA (orig_filename), emacs_strerror (errno));
              else if (nread > 0)
                {
                  struct buffer *prev = current_buffer;
@@ -3797,7 +3820,7 @@ actually used.  */)
                  buf->undo_list = Qt;
                  buf->overlays_before = Qnil;
                  buf->overlays_after = Qnil;
-                 
+
                  set_buffer_internal (buf);
                  Ferase_buffer ();
                  buf->enable_multibyte_characters = Qnil;
@@ -3807,7 +3830,7 @@ actually used.  */)
                  val = call2 (Vset_auto_coding_function,
                               filename, make_number (nread));
                  set_buffer_internal (prev);
-                 
+
                  /* Discard the unwind protect for recovering the
                      current buffer.  */
                  specpdl_ptr--;
@@ -3896,7 +3919,7 @@ actually used.  */)
          nread = emacs_read (fd, buffer, sizeof buffer);
          if (nread < 0)
            error ("IO error reading %s: %s",
-                  XSTRING (orig_filename)->data, emacs_strerror (errno));
+                  SDATA (orig_filename), emacs_strerror (errno));
          else if (nread == 0)
            break;
 
@@ -3967,16 +3990,16 @@ actually used.  */)
              nread = emacs_read (fd, buffer + total_read, trial - total_read);
              if (nread < 0)
                error ("IO error reading %s: %s",
-                      XSTRING (orig_filename)->data, emacs_strerror (errno));
+                      SDATA (orig_filename), emacs_strerror (errno));
              else if (nread == 0)
                break;
              total_read += nread;
            }
-         
+
          /* Scan this bufferful from the end, comparing with
             the Emacs buffer.  */
          bufpos = total_read;
-         
+
          /* Compare with same_at_start to avoid counting some buffer text
             as matching both at the file's beginning and at the end.  */
          while (bufpos > 0 && same_at_end > same_at_start
@@ -4150,7 +4173,7 @@ actually used.  */)
 
          if (how_much == -1)
            error ("IO error reading %s: %s",
-                  XSTRING (orig_filename)->data, emacs_strerror (errno));
+                  SDATA (orig_filename), emacs_strerror (errno));
          else if (how_much == -2)
            error ("maximum buffer size exceeded");
        }
@@ -4233,7 +4256,7 @@ actually used.  */)
       if (coding.cmp_data && coding.cmp_data->used)
        coding_restore_composition (&coding, Fcurrent_buffer ());
       coding_free_composition_data (&coding);
-  
+
       /* Set `inserted' to the number of inserted characters.  */
       inserted = PT - temp;
 
@@ -4278,15 +4301,15 @@ actually used.  */)
      before exiting the loop, it is set to a negative value if I/O
      error occurs.  */
   how_much = 0;
-  
+
   /* Total bytes inserted.  */
   inserted = 0;
-  
+
   /* Here, we don't do code conversion in the loop.  It is done by
      code_convert_region after all data are read into the buffer.  */
   {
     int gap_size = GAP_SIZE;
-    
+
     while (how_much < total)
       {
        /* try is reserved in some compilers (Microsoft C) */
@@ -4330,7 +4353,7 @@ actually used.  */)
            this = emacs_read (fd, BEG_ADDR + PT_BYTE - BEG_BYTE + inserted, trytry);
            immediate_quit = 0;
          }
-      
+
        if (this <= 0)
          {
            how_much = this;
@@ -4370,7 +4393,7 @@ actually used.  */)
 
   if (how_much < 0)
     error ("IO error reading %s: %s",
-          XSTRING (orig_filename)->data, emacs_strerror (errno));
+          SDATA (orig_filename), emacs_strerror (errno));
 
  notfound:
 
@@ -4395,7 +4418,7 @@ actually used.  */)
             this way, we can run Lisp program safely before decoding
             the inserted text.  */
          Lisp_Object unwind_data;
-             int count = specpdl_ptr - specpdl;
+             int count = SPECPDL_INDEX ();
 
          unwind_data = Fcons (current_buffer->enable_multibyte_characters,
                               Fcons (current_buffer->undo_list,
@@ -4474,11 +4497,13 @@ actually used.  */)
                             inserted);
     }
 
+  /* Now INSERTED is measured in characters.  */
+
 #ifdef DOS_NT
   /* Use the conversion type to determine buffer-file-type
      (find-buffer-file-type is now used to help determine the
      conversion).  */
-  if ((coding.eol_type == CODING_EOL_UNDECIDED 
+  if ((coding.eol_type == CODING_EOL_UNDECIDED
        || coding.eol_type == CODING_EOL_LF)
       && ! CODING_REQUIRE_DECODING (&coding))
     current_buffer->buffer_file_type = Qt;
@@ -4493,7 +4518,7 @@ actually used.  */)
       if (!EQ (current_buffer->undo_list, Qt))
        current_buffer->undo_list = Qnil;
 #ifdef APOLLO
-      stat (XSTRING (filename)->data, &st);
+      stat (SDATA (filename), &st);
 #endif
 
       if (NILP (handler))
@@ -4519,11 +4544,24 @@ actually used.  */)
                        Fcons (orig_filename, Qnil)));
     }
 
+  if (set_coding_system)
+    Vlast_coding_system_used = coding.symbol;
+
+  if (! NILP (Ffboundp (Qafter_insert_file_set_coding)))
+    {
+      insval = call1 (Qafter_insert_file_set_coding, make_number (inserted));
+      if (! NILP (insval))
+       {
+         CHECK_NUMBER (insval);
+         inserted = XFASTINT (insval);
+       }
+    }
+
   /* Decode file format */
   if (inserted > 0)
     {
       int empty_undo_list_p = 0;
-      
+
       /* If we're anyway going to discard undo information, don't
         record it in the first place.  The buffer's undo list at this
         point is either nil or t when visiting a file.  */
@@ -4532,19 +4570,16 @@ actually used.  */)
          empty_undo_list_p = NILP (current_buffer->undo_list);
          current_buffer->undo_list = Qt;
        }
-         
+
       insval = call3 (Qformat_decode,
                      Qnil, make_number (inserted), visit);
       CHECK_NUMBER (insval);
       inserted = XFASTINT (insval);
-      
+
       if (!NILP (visit))
        current_buffer->undo_list = empty_undo_list_p ? Qnil : Qt;
     }
 
-  if (set_coding_system)
-    Vlast_coding_system_used = coding.symbol;
-
   /* Call after-change hooks for the inserted text, aside from the case
      of normal visiting (not with REPLACE), which is done in a new buffer
      "before" the buffer is changed.  */
@@ -4625,7 +4660,15 @@ choose_write_coding_system (start, end, filename,
   if (auto_saving)
     val = Qnil;
   else if (!NILP (Vcoding_system_for_write))
-    val = Vcoding_system_for_write;
+    {
+      val = Vcoding_system_for_write;
+      if (coding_system_require_warning
+         && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
+       /* Confirm that VAL can surely encode the current region.  */
+       val = call5 (Vselect_safe_coding_system_function,
+                    start, end, Fcons (Qt, Fcons (val, Qnil)),
+                    Qnil, filename);
+    }
   else
     {
       /* If the variable `buffer-file-coding-system' is set locally,
@@ -4648,7 +4691,7 @@ choose_write_coding_system (start, end, filename,
          if (NILP (current_buffer->enable_multibyte_characters))
            force_raw_text = 1;
        }
-       
+
       if (NILP (val))
        {
          /* Check file-coding-system-alist.  */
@@ -4670,7 +4713,7 @@ choose_write_coding_system (start, end, filename,
          val = current_buffer->buffer_file_coding_system;
          using_default_coding = 1;
        }
-           
+
       if (!force_raw_text
          && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
        /* Confirm that VAL can surely encode the current region.  */
@@ -4730,7 +4773,7 @@ If VISIT is a string, it is a second file name;
   the output goes to FILENAME, but the buffer is marked as visiting VISIT.
   VISIT is also the file name to lock and unlock for clash detection.
 If VISIT is neither t nor nil nor a string,
-  that means do not print the \"Wrote file\" message.
+  that means do not display the \"Wrote file\" message.
 The optional sixth arg LOCKNAME, if non-nil, specifies the name to
   use for locking and unlocking, overriding FILENAME and VISIT.
 The optional seventh arg MUSTBENEW, if non-nil, insists on a check
@@ -4750,10 +4793,10 @@ This does code conversion according to the value of
   register int desc;
   int failure;
   int save_errno = 0;
-  unsigned char *fn;
+  const unsigned char *fn;
   struct stat st;
   int tem;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   int count1;
 #ifdef VMS
   unsigned char *fname = 0;     /* If non-0, original filename (must rename) */
@@ -4825,7 +4868,7 @@ This does code conversion according to the value of
     }
 
   record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
-  count1 = specpdl_ptr - specpdl;
+  count1 = SPECPDL_INDEX ();
 
   given_buffer = current_buffer;
 
@@ -4880,7 +4923,7 @@ This does code conversion according to the value of
 
   encoded_filename = ENCODE_FILE (filename);
 
-  fn = XSTRING (encoded_filename)->data;
+  fn = SDATA (encoded_filename);
   desc = -1;
   if (!NILP (append))
 #ifdef DOS_NT
@@ -4897,7 +4940,7 @@ This does code conversion according to the value of
        desc = emacs_open (fn, O_RDWR, 0);
        if (desc < 0)
          desc = creat_copy_attrs (STRINGP (current_buffer->filename)
-                                  ? XSTRING (current_buffer->filename)->data : 0,
+                                  ? SDATA (current_buffer->filename) : 0,
                                   fn);
       }
     else                /* Write to temporary name and rename if no errors */
@@ -4909,8 +4952,8 @@ This does code conversion according to the value of
          {
            temp_name = Fmake_temp_name (concat2 (temp_name,
                                                  build_string ("$$SAVE$$")));
-           fname = XSTRING (filename)->data;
-           fn = XSTRING (temp_name)->data;
+           fname = SDATA (filename);
+           fn = SDATA (temp_name);
            desc = creat_copy_attrs (fname, fn);
            if (desc < 0)
              {
@@ -4964,7 +5007,7 @@ This does code conversion according to the value of
   if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
     {
       long ret;
-      
+
       if (NUMBERP (append))
        ret = lseek (desc, XINT (append), 1);
       else
@@ -4978,7 +5021,7 @@ This does code conversion according to the value of
          report_file_error ("Lseek error", Fcons (filename, Qnil));
        }
     }
-  
+
   UNGCPRO;
 
 #ifdef VMS
@@ -5019,7 +5062,7 @@ This does code conversion according to the value of
 
   if (STRINGP (start))
     {
-      failure = 0 > a_write (desc, start, 0, XSTRING (start)->size,
+      failure = 0 > a_write (desc, start, 0, SCHARS (start),
                             &annotations, &coding);
       save_errno = errno;
     }
@@ -5129,7 +5172,7 @@ This does code conversion according to the value of
     current_buffer->modtime = st.st_mtime;
 
   if (failure)
-    error ("IO error writing %s: %s", XSTRING (filename)->data,
+    error ("IO error writing %s: %s", SDATA (filename),
           emacs_strerror (save_errno));
 
   if (visiting)
@@ -5210,7 +5253,7 @@ build_annotations (start, end)
   for (i = 0; CONSP (p); p = XCDR (p), ++i)
     {
       struct buffer *given_buffer = current_buffer;
-      
+
       Vwrite_region_annotations_so_far = annotations;
 
       /* Value is either a list of annotations or nil if the function
@@ -5224,7 +5267,7 @@ build_annotations (start, end)
          XSETFASTINT (end, ZV);
          annotations = Qnil;
        }
-      
+
       if (CONSP (res))
        annotations = merge (annotations, res, Qcar_less_than_car);
     }
@@ -5304,7 +5347,7 @@ a_write (desc, string, pos, nchars, annot, coding)
       tem = Fcdr (Fcar (*annot));
       if (STRINGP (tem))
        {
-         if (0 > e_write (desc, tem, 0, XSTRING (tem)->size, coding))
+         if (0 > e_write (desc, tem, 0, SCHARS (tem), coding))
            return -1;
        }
       *annot = Fcdr (*annot);
@@ -5340,8 +5383,8 @@ e_write (desc, string, start, end, coding)
 
   if (STRINGP (string))
     {
-      addr = XSTRING (string)->data;
-      nbytes = STRING_BYTES (XSTRING (string));
+      addr = SDATA (string);
+      nbytes = SBYTES (string);
       coding->src_multibyte = STRING_MULTIBYTE (string);
     }
   else if (start < end)
@@ -5429,7 +5472,7 @@ This means that the file has not been changed since it was visited or saved.  */
 
   filename = ENCODE_FILE (b->filename);
 
-  if (stat (XSTRING (filename)->data, &st) < 0)
+  if (stat (SDATA (filename), &st) < 0)
     {
       /* If the file doesn't exist now and didn't exist before,
         we say that it isn't modified, provided the error is a tame one.  */
@@ -5497,7 +5540,7 @@ An argument specifies the modification time value to use
 
       filename = ENCODE_FILE (filename);
 
-      if (stat (XSTRING (filename)->data, &st) >= 0)
+      if (stat (SDATA (filename), &st) >= 0)
        current_buffer->modtime = st.st_mtime;
     }
 
@@ -5511,22 +5554,22 @@ auto_save_error (error)
   Lisp_Object args[3], msg;
   int i, nbytes;
   struct gcpro gcpro1;
-  
+
   ring_bell ();
-  
+
   args[0] = build_string ("Auto-saving %s: %s");
   args[1] = current_buffer->name;
   args[2] = Ferror_message_string (error);
   msg = Fformat (3, args);
   GCPRO1 (msg);
-  nbytes = STRING_BYTES (XSTRING (msg));
+  nbytes = SBYTES (msg);
 
   for (i = 0; i < 3; ++i)
     {
       if (i == 0)
-       message2 (XSTRING (msg)->data, nbytes, STRING_MULTIBYTE (msg));
+       message2 (SDATA (msg), nbytes, STRING_MULTIBYTE (msg));
       else
-       message2_nolog (XSTRING (msg)->data, nbytes, STRING_MULTIBYTE (msg));
+       message2_nolog (SDATA (msg), nbytes, STRING_MULTIBYTE (msg));
       Fsleep_for (make_number (1), Qnil);
     }
 
@@ -5541,7 +5584,7 @@ auto_save_1 ()
 
   /* Get visited file's mode to become the auto save file's mode.  */
   if (! NILP (current_buffer->filename)
-      && stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
+      && stat (SDATA (current_buffer->filename), &st) >= 0)
     /* But make sure we can overwrite it later!  */
     auto_save_mode_bits = st.st_mode | 0600;
   else
@@ -5561,7 +5604,6 @@ do_auto_save_unwind (stream)  /* used as unwind-protect function */
   if (!NILP (stream))
     fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
                      | XFASTINT (XCDR (stream))));
-  pop_message ();
   return Qnil;
 }
 
@@ -5573,6 +5615,20 @@ do_auto_save_unwind_1 (value)  /* used as unwind-protect function */
   return Qnil;
 }
 
+static Lisp_Object
+do_auto_save_make_dir (dir)
+     Lisp_Object dir;
+{
+  return call2 (Qmake_directory, dir, Qt);
+}
+
+static Lisp_Object
+do_auto_save_eh (ignore)
+     Lisp_Object ignore;
+{
+  return Qnil;
+}
+
 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
        doc: /* Auto-save all buffers that need it.
 This is all buffers that have auto-saving enabled
@@ -5594,9 +5650,10 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   Lisp_Object oquit;
   FILE *stream;
   Lisp_Object lispstream;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   int orig_minibuffer_auto_raise = minibuffer_auto_raise;
-  int message_p = 0;
+  int old_message_p = 0;
+  struct gcpro gcpro1, gcpro2;
 
   if (max_specpdl_size < specpdl_size + 40)
     max_specpdl_size = specpdl_size + 40;
@@ -5604,9 +5661,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   if (minibuf_level)
     no_message = Qt;
 
-  if (NILP (no_message));
-    message_p = push_message ();
-  
+  if (NILP (no_message))
+    {
+      old_message_p = push_message ();
+      record_unwind_protect (pop_message_unwind, Qnil);
+    }
+
   /* Ordinarily don't quit within this function,
      but don't make it impossible to quit (in case we get hung in I/O).  */
   oquit = Vquit_flag;
@@ -5621,7 +5681,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   if (STRINGP (Vauto_save_list_file_name))
     {
       Lisp_Object listfile;
-      
+
       listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
 
       /* Don't try to create the directory when shutting down Emacs,
@@ -5630,12 +5690,17 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
       if (!NILP (Vrun_hooks))
        {
          Lisp_Object dir;
+         dir = Qnil;
+         GCPRO2 (dir, listfile);
          dir = Ffile_name_directory (listfile);
          if (NILP (Ffile_directory_p (dir)))
-           call2 (Qmake_directory, dir, Qt);
+           internal_condition_case_1 (do_auto_save_make_dir,
+                                      dir, Fcons (Fcons (Qfile_error, Qnil), Qnil),
+                                      do_auto_save_eh);
+         UNGCPRO;
        }
-      
-      stream = fopen (XSTRING (listfile)->data, "w");
+
+      stream = fopen (SDATA (listfile), "w");
       if (stream != NULL)
        {
          /* Arrange to close that file whether or not we get an error.
@@ -5678,12 +5743,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
          {
            if (!NILP (b->filename))
              {
-               fwrite (XSTRING (b->filename)->data, 1,
-                       STRING_BYTES (XSTRING (b->filename)), stream);
+               fwrite (SDATA (b->filename), 1,
+                       SBYTES (b->filename), stream);
              }
            putc ('\n', stream);
-           fwrite (XSTRING (b->auto_save_file_name)->data, 1,
-                   STRING_BYTES (XSTRING (b->auto_save_file_name)), stream);
+           fwrite (SDATA (b->auto_save_file_name), 1,
+                   SBYTES (b->auto_save_file_name), stream);
            putc ('\n', stream);
          }
 
@@ -5760,17 +5825,22 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
 
   if (auto_saved && NILP (no_message))
     {
-      if (message_p)
+      if (old_message_p)
        {
+         /* If we are going to restore an old message,
+            give time to read ours.  */
          sit_for (1, 0, 0, 0, 0);
          restore_message ();
        }
       else
+       /* If we displayed a message and then restored a state
+          with no message, leave a "done" message on the screen.  */
        message1 ("Auto-saving...done");
     }
 
   Vquit_flag = oquit;
 
+  /* This restores the message-stack status.  */
   unbind_to (count, Qnil);
   return Qnil;
 }
@@ -5813,21 +5883,22 @@ static Lisp_Object
 double_dollars (val)
      Lisp_Object val;
 {
-  register unsigned char *old, *new;
+  register const unsigned char *old;
+  register unsigned char *new;
   register int n;
   int osize, count;
 
-  osize = STRING_BYTES (XSTRING (val));
+  osize = SBYTES (val);
 
   /* Count the number of $ characters.  */
-  for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
+  for (n = osize, count = 0, old = SDATA (val); n > 0; n--)
     if (*old++ == '$') count++;
   if (count > 0)
     {
-      old = XSTRING (val)->data;
-      val = make_uninit_multibyte_string (XSTRING (val)->size + count,
+      old = SDATA (val);
+      val = make_uninit_multibyte_string (SCHARS (val) + count,
                                          osize + count);
-      new = XSTRING (val)->data;
+      new = SDATA (val);
       for (n = osize; n > 0; n--)
        if (*old != '$')
          *new++ = *old++;
@@ -5870,7 +5941,7 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
   /* No need to protect ACTION--we only compare it with t and nil.  */
   GCPRO5 (string, realdir, name, specdir, orig_string);
 
-  if (XSTRING (string)->size == 0)
+  if (SCHARS (string) == 0)
     {
       if (EQ (action, Qlambda))
        {
@@ -5924,15 +5995,15 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
 #ifndef VMS
       if (EQ (Vread_file_name_predicate, Qfile_directory_p))
        {
-         /* Brute-force speed up for directory checking: 
+         /* 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 = XSTRING (tem)->size, len > 0) &&
-                 IS_DIRECTORY_SEP (XSTRING (tem)->data[len-1]))
+                 (len = SCHARS (tem), len > 0) &&
+                 IS_DIRECTORY_SEP (SREF (tem, len-1)))
                comp = Fcons (tem, comp);
            }
        }
@@ -5941,7 +6012,7 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
        {
          /* Must do it the hard (and slow) way.  */
          GCPRO3 (all, comp, specdir);
-         count = specpdl_ptr - specpdl;
+         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))
@@ -5957,7 +6028,7 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
 #ifdef VMS
   /* Supposedly this helps commands such as `cd' that read directory names,
      but can someone explain how it helps them? -- RMS */
-  if (XSTRING (name)->size == 0)
+  if (SCHARS (name) == 0)
     return Qt;
 #endif /* VMS */
   if (!NILP (Vread_file_name_predicate))
@@ -5974,7 +6045,7 @@ Default name to DEFAULT-FILENAME if user enters a null string.
 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 
+If optional sixth arg PREDICATE is non-nil, possible completions and the
 resulting file name must satisfy (funcall PREDICATE NAME).
 DIR defaults to current buffer's directory default.
 
@@ -5987,6 +6058,7 @@ provides a file dialog box.  */)
   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;
@@ -5994,12 +6066,9 @@ provides a file dialog box.  */)
   if (NILP (dir))
     dir = current_buffer->directory;
   if (NILP (default_filename))
-    {
-      if (! NILP (initial))
-       default_filename = Fexpand_file_name (initial, dir);
-      else
-       default_filename = current_buffer->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");
@@ -6012,25 +6081,29 @@ provides a file dialog box.  */)
       CORRECT_DIR_SEPS (homedir);
     }
 #endif
+  if (homedir != 0)
+    decoded_homedir
+      = DECODE_FILE (make_unibyte_string (homedir, strlen (homedir)));
   if (homedir != 0
       && STRINGP (dir)
-      && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
-      && IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
+      && !strncmp (SDATA (decoded_homedir), SDATA (dir),
+                  SBYTES (decoded_homedir))
+      && IS_DIRECTORY_SEP (SREF (dir, SBYTES (decoded_homedir))))
     {
-      dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
-                        STRING_BYTES (XSTRING (dir)) - strlen (homedir) + 1);
-      XSTRING (dir)->data[0] = '~';
+      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 (homedir, XSTRING (default_filename)->data, strlen (homedir))
-      && IS_DIRECTORY_SEP (XSTRING (default_filename)->data[strlen (homedir)]))
+      && !strncmp (SDATA (decoded_homedir), SDATA (default_filename),
+                  SBYTES (decoded_homedir))
+      && IS_DIRECTORY_SEP (SREF (default_filename, SBYTES (decoded_homedir))))
     {
       default_filename
-       = make_string (XSTRING (default_filename)->data + strlen (homedir) - 1,
-                      STRING_BYTES (XSTRING (default_filename)) - strlen (homedir) + 1);
-      XSTRING (default_filename)->data[0] = '~';
+       = Fsubstring (default_filename,
+                     make_number (SCHARS (decoded_homedir)), Qnil);
+      default_filename = concat2 (build_string ("~"), default_filename);
     }
   if (!NILP (default_filename))
     {
@@ -6048,7 +6121,7 @@ provides a file dialog box.  */)
          args[0] = insdef;
          args[1] = initial;
          insdef = Fconcat (2, args);
-         pos = make_number (XSTRING (double_dollars (dir))->size);
+         pos = make_number (SCHARS (double_dollars (dir)));
          insdef = Fcons (double_dollars (insdef), pos);
        }
       else
@@ -6074,18 +6147,18 @@ provides a file dialog box.  */)
       RETURN_UNGCPRO (Ffuncall (7, args));
     }
 
-  count = specpdl_ptr - specpdl;
+  count = SPECPDL_INDEX ();
 #ifdef VMS
   specbind (intern ("completion-ignore-case"), Qt);
 #endif
 
   specbind (intern ("minibuffer-completing-file-name"), Qt);
-  specbind (intern ("read-file-name-predicate"), 
+  specbind (intern ("read-file-name-predicate"),
            (NILP (predicate) ? Qfile_exists_p : predicate));
 
   GCPRO2 (insdef, default_filename);
-  
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI)
+
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
       && use_dialog_box
       && have_menus_p ())
@@ -6093,7 +6166,7 @@ provides a file dialog box.  */)
       /* If DIR contains a file name, split it.  */
       Lisp_Object file;
       file = Ffile_name_nondirectory (dir);
-      if (XSTRING (file)->size && NILP (default_filename))
+      if (SCHARS (file) && NILP (default_filename))
        {
          default_filename = file;
          dir = Ffile_name_directory (dir);
@@ -6125,7 +6198,7 @@ provides a file dialog box.  */)
       if (! replace_in_history)
        add_to_history = 1;
 
-      val = build_string ("");
+      val = empty_string;
     }
 
   unbind_to (count, Qnil);
@@ -6137,7 +6210,7 @@ provides a file dialog box.  */)
 
   if (!NILP (tem) && !NILP (default_filename))
     val = default_filename;
-  else if (XSTRING (val)->size == 0 && NILP (insdef))
+  else if (SCHARS (val) == 0 && NILP (insdef))
     {
       if (!NILP (default_filename))
        val = default_filename;
@@ -6160,7 +6233,7 @@ provides a file dialog box.  */)
        Fset (Qfile_name_history,
              Fcons (val1, tem));
     }
-    
+
   return val;
 }
 
@@ -6285,7 +6358,9 @@ same format as a regular save would use.  */);
   staticpro (&Qformat_decode);
   Qformat_annotate_function = intern ("format-annotate-function");
   staticpro (&Qformat_annotate_function);
-       
+  Qafter_insert_file_set_coding = intern ("after-insert-file-set-coding");
+  staticpro (&Qafter_insert_file_set_coding);
+
   Qcar_less_than_car = intern ("car-less-than-car");
   staticpro (&Qcar_less_than_car);
 
@@ -6325,13 +6400,7 @@ nil means use format `var'.  This variable is meaningful only on VMS.  */);
 
   DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
               doc: /* Directory separator character for built-in functions that return file names.
-The value should be either ?/ or ?\\ (any other value is treated as ?\\).
-This variable affects the built-in functions only on Windows,
-on other platforms, it is initialized so that Lisp code can find out
-what the normal separator is.
-
-WARNING: This variable is deprecated and will be removed in the near
-future.  DO NOT USE IT.  */);
+The value is always ?/.  Don't use this variable, just use `/'.  */);
 
   DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
               doc: /* *Alist of elements (REGEXP . HANDLER) for file names handled specially.
@@ -6363,10 +6432,11 @@ or local variable spec of the tailing lines with `coding:' tag.  */);
 
   DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
               doc: /* A list of functions to be called at the end of `insert-file-contents'.
-Each is passed one argument, the number of bytes inserted.  It should return
-the new byte count, and leave point the same.  If `insert-file-contents' is
-intercepted by a handler from `file-name-handler-alist', that handler is
-responsible for calling the after-insert-file-functions if appropriate.  */);
+Each is passed one argument, the number of characters inserted.
+It should return the new character count, and leave point the same.
+If `insert-file-contents' is intercepted by a handler from
+`file-name-handler-alist', that handler is responsible for calling the
+functions in `after-insert-file-functions' if appropriate.  */);
   Vafter_insert_file_functions = Qnil;
 
   DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
@@ -6463,4 +6533,3 @@ a non-nil value.  */);
   defsubr (&Sunix_sync);
 #endif
 }
-