diff src/fileio.c @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents ee648375d8d6
children 54cc21c15cbb
line wrap: on
line diff
--- a/src/fileio.c	Mon Aug 13 09:00:04 2007 +0200
+++ b/src/fileio.c	Mon Aug 13 09:02:59 2007 +0200
@@ -32,6 +32,9 @@
 #include "redisplay.h"
 #include "sysdep.h"
 #include "window.h"             /* minibuf_level */
+#ifdef MULE
+#include "mule-coding.h"
+#endif
 
 #ifdef HAVE_LIBGEN_H            /* Must come before sysfile.h */
 #include <libgen.h>
@@ -112,19 +115,13 @@
 DOESNT_RETURN
 report_file_error (CONST char *string, Lisp_Object data)
 {
-  /* #### dmoore - This uses current_buffer, better make sure no one
-     has GC'd the current buffer.  File handlers are giving me a headache
-     maybe I'll just always protect current_buffer around all of those
-     calls. */
-
   /* mrb: #### Needs to be fixed at a lower level; errstring needs to
      be MULEized.  The following at least prevents a crash... */
   Lisp_Object errstring = build_ext_string (strerror (errno), FORMAT_BINARY);
 
   /* System error messages are capitalized.  Downcase the initial
      unless it is followed by a slash.  */
-  if (string_char_length (XSTRING (errstring)) >= 2
-      && string_char (XSTRING (errstring), 1) != '/')
+  if (string_char (XSTRING (errstring), 1) != '/')
     set_string_char (XSTRING (errstring), 0,
 		     DOWNCASE (current_buffer,
 			       string_char (XSTRING (errstring), 0)));
@@ -340,7 +337,6 @@
 */
        (filename, operation))
 {
-  /* This function does not GC */
   /* This function must not munge the match data.  */
   Lisp_Object chain, inhibited_handlers;
 
@@ -375,27 +371,17 @@
 static Lisp_Object
 call2_check_string (Lisp_Object fn, Lisp_Object arg0, Lisp_Object arg1)
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object result = call2 (fn, arg0, arg1);
   CHECK_STRING (result);
   return (result);
 }
 
 static Lisp_Object
-call2_check_string_or_nil (Lisp_Object fn, Lisp_Object arg0, Lisp_Object arg1)
-{
-  /* This function can call lisp */
-  Lisp_Object result = call2 (fn, arg0, arg1);
-  if (!NILP (result))
-    CHECK_STRING (result);
-  return (result);
-}
-
-static Lisp_Object
 call3_check_string (Lisp_Object fn, Lisp_Object arg0, 
                     Lisp_Object arg1, Lisp_Object arg2)
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object result = call3 (fn, arg0, arg1, arg2);
   CHECK_STRING (result);
   return (result);
@@ -411,7 +397,7 @@
 */
        (file))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Bufbyte *beg;
   Bufbyte *p;
   Lisp_Object handler;
@@ -422,8 +408,14 @@
      call the corresponding file handler.  */
   handler = Ffind_file_name_handler (file, Qfile_name_directory);
   if (!NILP (handler))
-    return (call2_check_string_or_nil (handler, Qfile_name_directory,
-				       file));
+    {
+      Lisp_Object retval = call2 (handler, Qfile_name_directory,
+				  file);
+
+      if (!NILP (retval))
+	CHECK_STRING (retval);
+      return retval;
+    }
 
 #ifdef FILE_SYSTEM_CASE
   file = FILE_SYSTEM_CASE (file);
@@ -479,7 +471,7 @@
 */
        (file))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Bufbyte *beg, *p, *end;
   Lisp_Object handler;
 
@@ -513,9 +505,9 @@
 The `call-process' and `start-process' functions use this function to
 get a current directory to run processes in.
 */
-       (filename))
+  (filename))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Lisp_Object handler;
 
   /* If the file name has special constructs in it,
@@ -615,7 +607,7 @@
 */
        (file))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   char *buf;
   Lisp_Object handler;
 
@@ -801,7 +793,7 @@
 */
        (directory))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   char *buf;
   Lisp_Object handler;
 
@@ -869,7 +861,7 @@
 */
        (name, defalt))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Bufbyte *nm;
   
   Bufbyte *newdir, *p, *o;
@@ -919,11 +911,7 @@
 
   if (!NILP (defalt))
     {
-      struct gcpro gcpro1;
-
-      GCPRO1 (defalt);		/* might be current_buffer->directory */
       handler = Ffind_file_name_handler (defalt, Qexpand_file_name);
-      UNGCPRO;
       if (!NILP (handler))
 	return call3 (handler, Qexpand_file_name, name, defalt);
     }
@@ -938,15 +926,15 @@
      Putting this call here avoids all that crud.
 
      The EQ test avoids infinite recursion.  */
-  if (! NILP(defalt) && !EQ (defalt, name)
+  if (! NILP (defalt) && !EQ (defalt, name)
       /* This saves time in a common case.  */
       && ! (XSTRING_LENGTH (defalt) >= 3
-	    && (IS_DIRECTORY_SEP (XSTRING_BYTE (defalt, 0))
-		|| IS_DEVICE_SEP (XSTRING_BYTE (defalt, 1)))))
+	    && IS_DIRECTORY_SEP (string_byte (XSTRING (defalt), 0))
+	    && IS_DEVICE_SEP (string_byte (XSTRING (defalt), 1))))
     {
       struct gcpro gcpro1;
 
-      GCPRO1 (defalt);		/* may be current_buffer->directory */
+      GCPRO1 (name);
       defalt = Fexpand_file_name (defalt, Qnil);
       UNGCPRO;
     }
@@ -959,8 +947,6 @@
   name = FILE_SYSTEM_CASE (name);
 #endif
 
-  /* #### dmoore - this is ugly, clean this up.  Looks like nm
-     pointing into name should be safe during all of this, though. */
   nm = XSTRING_DATA (name);
   
 #ifdef MSDOS
@@ -1398,14 +1384,16 @@
 */
        (filename, defalt))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
+  struct gcpro gcpro1;
   Lisp_Object expanded_name;
   Lisp_Object handler;
-  struct gcpro gcpro1;
 
   CHECK_STRING (filename);
 
+  GCPRO1 (filename);
   expanded_name = Fexpand_file_name (filename, defalt);
+  UNGCPRO;
 
   if (!STRINGP (expanded_name))
     return Qnil;
@@ -1489,7 +1477,7 @@
 
     {
       int rlen = strlen (resolved_path);
-      if (elen > 0 && XSTRING_BYTE (expanded_name, elen - 1) == '/'
+      if (elen > 0 && string_byte (XSTRING (expanded_name), elen - 1) == '/'
           && !(rlen > 0 && resolved_path[rlen - 1] == '/'))
 	{
 	  if (rlen + 1 > countof (resolved_path))
@@ -1525,7 +1513,6 @@
 */
        (string))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
   Bufbyte *nm;
 
   Bufbyte *s, *p, *o, *x, *endp;
@@ -1541,8 +1528,14 @@
      call the corresponding file handler.  */
   handler = Ffind_file_name_handler (string, Qsubstitute_in_file_name);
   if (!NILP (handler))
-    return (call2_check_string_or_nil (handler, Qsubstitute_in_file_name,
-				       string));
+    {
+      Lisp_Object retval = call2 (handler, Qsubstitute_in_file_name,
+				  string);
+
+      if (!NILP (retval))
+	CHECK_STRING (retval);
+      return retval;
+    }
 
   nm = XSTRING_DATA (string);
 #ifdef MSDOS
@@ -1736,16 +1729,16 @@
 Lisp_Object
 expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   struct gcpro gcpro1;
 
+  GCPRO1 (filename);
   abspath = Fexpand_file_name (filename, defdir);
-  GCPRO1 (abspath);
 #ifdef VMS
   {
     Bufbyte c =
-      XSTRING_BYTE (abspath, XSTRING_LENGTH (abspath) - 1);
+      string_byte (XSTRING (abspath), XSTRING_LENGTH (abspath) - 1);
     if (c == ':' || c == ']' || c == '>')
       abspath = Fdirectory_file_name (abspath);
   }
@@ -1753,8 +1746,10 @@
   /* Remove final slash, if any (unless path is root).
      stat behaves differently depending!  */
   if (XSTRING_LENGTH (abspath) > 1
-      && IS_DIRECTORY_SEP (XSTRING_BYTE (abspath, XSTRING_LENGTH (abspath) - 1))
-      && !IS_DEVICE_SEP (XSTRING_BYTE (abspath, XSTRING_LENGTH (abspath) - 2)))
+      && IS_DIRECTORY_SEP (string_byte (XSTRING (abspath),
+					XSTRING_LENGTH (abspath) - 1))
+      && !IS_DEVICE_SEP (string_byte (XSTRING (abspath),
+				      XSTRING_LENGTH (abspath) - 2)))
     /* We cannot take shortcuts; they might be wrong for magic file names.  */
     abspath = Fdirectory_file_name (abspath);
 #endif
@@ -1774,7 +1769,6 @@
 barf_or_query_if_file_exists (Lisp_Object absname, CONST char *querystring,
 			      int interactive, struct stat *statptr)
 {
-  /* This function can call lisp */
   struct stat statbuf;
 
   /* stat is a good way to tell whether the file exists,
@@ -1782,24 +1776,19 @@
   if (stat ((char *) XSTRING_DATA (absname), &statbuf) >= 0)
     {
       Lisp_Object tem;
-
+      struct gcpro gcpro1;
+
+      GCPRO1 (absname);
       if (interactive)
-	{
-	  Lisp_Object prompt;
-	  struct gcpro gcpro1;
-
-	  prompt = emacs_doprnt_string_c
+        tem = call1
+	  (Qyes_or_no_p,
+	   (emacs_doprnt_string_c
 	    ((CONST Bufbyte *) GETTEXT ("File %s already exists; %s anyway? "),
 	     Qnil, -1, XSTRING_DATA (absname),
-	     GETTEXT (querystring));
-	     
-	  GCPRO1 (prompt);
-	  tem = call1 (Qyes_or_no_p, prompt);
-	  UNGCPRO;
-	}
+	     GETTEXT (querystring))));
       else
         tem = Qnil;
-
+      UNGCPRO;
       if (NILP (tem))
 	Fsignal (Qfile_already_exists,
 		 list2 (build_translated_string ("File already exists"),
@@ -1826,9 +1815,9 @@
 last-modified time as the old one.  (This works on only some systems.)
 A prefix arg makes KEEP-TIME non-nil.
 */
-       (filename, newname, ok_if_already_exists, keep_time))
+       (filename, newname, ok_if_already_exists, keep_date))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   int ifd, ofd, n;
   char buf[16 * 1024];
   struct stat st, out_st;
@@ -1854,7 +1843,7 @@
   {
     UNGCPRO;
     return call5 (handler, Qcopy_file, filename, newname,
-		  ok_if_already_exists, keep_time);
+		  ok_if_already_exists, keep_date);
   }
 
   /* When second argument is a directory, copy the file into it.
@@ -1870,7 +1859,8 @@
       args[1] = Qnil; args[2] = Qnil;
       NGCPRO1 (*args); 
       ngcpro1.nvars = 3;
-      if (XSTRING_BYTE (newname, XSTRING_LENGTH (newname) - 1) != '/')
+      if (string_byte (XSTRING (newname),
+		       XSTRING_LENGTH (newname) - 1) != '/')
 	args[i++] = build_string ("/");
       args[i++] = Ffile_name_nondirectory (filename);
       newname = Fconcat (i, args);
@@ -1954,7 +1944,7 @@
 
     if (input_file_statable_p)
     {
-      if (!NILP (keep_time))
+      if (!NILP (keep_date))
       {
         EMACS_TIME atime, mtime;
         EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
@@ -1994,19 +1984,21 @@
 */
        (dirname))
 {
-  /* This function can GC.  GC checked 1997.04.06 */
+  /* This function can GC */
   char dir [MAXPATHLEN];
   Lisp_Object handler;
+
   struct gcpro gcpro1;
   
+  GCPRO1 (dirname);
   CHECK_STRING (dirname);
   dirname = Fexpand_file_name (dirname, Qnil);
 
-  GCPRO1 (dirname);
   handler = Ffind_file_name_handler (dirname, Qmake_directory_internal);
   UNGCPRO;
   if (!NILP (handler))
-    return (call2 (handler, Qmake_directory_internal, dirname));
+    return (call2 (handler, Qmake_directory_internal,
+		   dirname));
  
   if (XSTRING_LENGTH (dirname) > (sizeof (dir) - 1))
     {
@@ -2038,15 +2030,14 @@
 */
        (dirname))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Lisp_Object handler;
   struct gcpro gcpro1;
   
+  GCPRO1 (dirname);
   CHECK_STRING (dirname);
-
-  GCPRO1 (dirname);
-  dirname = Fexpand_file_name (dirname, Qnil);
-  dirname =  Fdirectory_file_name (dirname);
+  dirname =
+    Fdirectory_file_name (Fexpand_file_name (dirname, Qnil));
 
   handler = Ffind_file_name_handler (dirname, Qdelete_directory);
   UNGCPRO;
@@ -2065,14 +2056,14 @@
 */
        (filename))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Lisp_Object handler;
   struct gcpro gcpro1;
   
+  GCPRO1 (filename);
   CHECK_STRING (filename);
   filename = Fexpand_file_name (filename, Qnil);
 
-  GCPRO1 (filename);
   handler = Ffind_file_name_handler (filename, Qdelete_file);
   UNGCPRO;
   if (!NILP (handler))
@@ -2094,7 +2085,6 @@
 int
 internal_delete_file (Lisp_Object filename)
 {
-  /* This function can GC.  GC checked 1997.04.06. */
   return NILP (condition_case_1 (Qt, Fdelete_file, filename,
 				 internal_delete_file_1, Qnil));
 }
@@ -2110,7 +2100,7 @@
 */
        (filename, newname, ok_if_already_exists))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2;
 
@@ -2203,7 +2193,7 @@
 */
        (filename, newname, ok_if_already_exists))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2;
 
@@ -2260,7 +2250,7 @@
 */
        (filename, linkname, ok_if_already_exists))
 {
-  /* This function can GC.  GC checked 1997.06.04. */
+  /* This function can GC */
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2;
 
@@ -2270,7 +2260,7 @@
   /* 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_BYTE (filename, 0) == '~') /* #### Un*x-specific */
+  if (string_byte (XSTRING (filename), 0) == '~') /* #### Un*x-specific */
     filename = Fexpand_file_name (filename, Qnil);
   linkname = Fexpand_file_name (linkname, Qnil);
 
@@ -2368,7 +2358,6 @@
 */
        (filename))
 {
-  /* This function does not GC */
   Bufbyte *ptr;
 
   CHECK_STRING (filename);
@@ -2448,14 +2437,16 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   Lisp_Object handler;
   struct stat statbuf;
   struct gcpro gcpro1;
   
+  GCPRO1 (filename);
   CHECK_STRING (filename);
   abspath = Fexpand_file_name (filename, Qnil);
+  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -2476,8 +2467,9 @@
 For a directory, this means you can access files in that directory.
 */
        (filename))
+
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   Lisp_Object handler;
   struct gcpro gcpro1;
@@ -2505,14 +2497,16 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   Lisp_Object handler;
   int desc;
   struct gcpro gcpro1;
   
+  GCPRO1 (filename);
   CHECK_STRING (filename);
   abspath = Fexpand_file_name (filename, Qnil);
+  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -2536,14 +2530,16 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath, dir;
   Lisp_Object handler;
   struct stat statbuf;
   struct gcpro gcpro1;
   
+  GCPRO1 (filename);
   CHECK_STRING (filename);
   abspath = Fexpand_file_name (filename, Qnil);
+  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -2558,16 +2554,10 @@
 	    ? Qt : Qnil);
 
 
-  GCPRO1 (abspath);
   dir = Ffile_name_directory (abspath);
-  UNGCPRO;
 #if defined (VMS) || defined (MSDOS)
   if (!NILP (dir))
-    {
-      GCPRO1(dir);
-      dir = Fdirectory_file_name (dir);
-      UNGCPRO;
-    }
+    dir = Fdirectory_file_name (dir);
 #endif /* VMS or MSDOS */
   return (check_writable (!NILP (dir) ? (char *) XSTRING_DATA (dir)
 			  : "")
@@ -2581,7 +2571,7 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
 #ifdef S_IFLNK
   char *buf;
   int bufsize;
@@ -2590,14 +2580,14 @@
   Lisp_Object handler;
   struct gcpro gcpro1;
   
+  GCPRO1 (filename);
   CHECK_STRING (filename);
   filename = Fexpand_file_name (filename, Qnil);
+  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  GCPRO1 (filename);
   handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
-  UNGCPRO;
   if (!NILP (handler))
     return call2 (handler, Qfile_symlink_p, filename);
 
@@ -2633,13 +2623,13 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   struct stat st;
   Lisp_Object handler;
   struct gcpro gcpro1;
   
-  GCPRO1 (current_buffer->directory);
+  GCPRO1 (filename);
   abspath = expand_and_dir_to_file (filename,
 				    current_buffer->directory);
   UNGCPRO;
@@ -2667,8 +2657,9 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object handler;
+  struct gcpro gcpro1;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -2677,10 +2668,15 @@
     return call2 (handler, Qfile_accessible_directory_p,
 		  filename);
 
+  GCPRO1 (filename);
   if (NILP (Ffile_directory_p (filename)))
+    {
+      UNGCPRO;
       return (Qnil);
-  else
-    return Ffile_executable_p (filename);
+    }
+  handler = Ffile_executable_p (filename);
+  UNGCPRO;
+  return (handler);
 }
 
 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /*
@@ -2689,21 +2685,15 @@
 */
        (filename))
 {
-  /* This function can call lisp */
-  Lisp_Object abspath;
+  REGISTER Lisp_Object abspath;
   struct stat st;
   Lisp_Object handler;
-  struct gcpro gcpro1;
-
-  GCPRO1 (current_buffer->directory);
+
   abspath = expand_and_dir_to_file (filename, current_buffer->directory);
-  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  GCPRO1 (abspath);
   handler = Ffind_file_name_handler (abspath, Qfile_regular_p);
-  UNGCPRO;
   if (!NILP (handler))
     return call2 (handler, Qfile_regular_p, abspath);
 
@@ -2717,13 +2707,13 @@
 */
        (filename))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   struct stat st;
   Lisp_Object handler;
   struct gcpro gcpro1;
   
-  GCPRO1 (current_buffer->directory);
+  GCPRO1 (filename);
   abspath = expand_and_dir_to_file (filename,
 				    current_buffer->directory);
   UNGCPRO;
@@ -2752,17 +2742,16 @@
 */
        (filename, mode))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath;
   Lisp_Object handler;
-  struct gcpro gcpro1;
+  struct gcpro gcpro1, gcpro2;
   
-  GCPRO1 (current_buffer->directory);
+  GCPRO2 (filename, mode);
   abspath = Fexpand_file_name (filename, current_buffer->directory);
+  CHECK_INT (mode);
   UNGCPRO;
 
-  CHECK_INT (mode);
-
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
   GCPRO1 (abspath);
@@ -2828,25 +2817,27 @@
 */
        (file1, file2))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   Lisp_Object abspath1, abspath2;
   struct stat st;
   int mtime1;
   Lisp_Object handler;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2;
 
   CHECK_STRING (file1);
   CHECK_STRING (file2);
 
   abspath1 = Qnil;
-  abspath2 = Qnil;
-
-  GCPRO3 (abspath1, abspath2, current_buffer->directory);
-  abspath1 = expand_and_dir_to_file (file1, current_buffer->directory);
-  abspath2 = expand_and_dir_to_file (file2, current_buffer->directory);
+  GCPRO2 (abspath1, file2);
+  abspath1 = expand_and_dir_to_file (file1,
+				     current_buffer->directory);
+  abspath2 = expand_and_dir_to_file (file2,
+				     current_buffer->directory);
+  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
+  GCPRO2 (abspath1, abspath2);
   handler = Ffind_file_name_handler (abspath1, Qfile_newer_than_file_p);
   if (NILP (handler))
     handler = Ffind_file_name_handler (abspath2, Qfile_newer_than_file_p);
@@ -2876,39 +2867,36 @@
 #define READ_BUF_SIZE (1 << 15)
 
 DEFUN ("insert-file-contents-internal",
-       Finsert_file_contents_internal, 1, 5, 0, /*
-Insert contents of file FILENAME after point.
-Returns list of absolute file name and length of data 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
-before the error is signaled.
-
-The optional third and fourth arguments BEG and END
-specify what portion of the file to insert.
-If VISIT is non-nil, BEG and END must be nil.
-If optional fifth argument REPLACE is non-nil,
-it means replace the current buffer contents (in the accessible portion)
-with the file contents.  This is better than simply deleting and inserting
-the whole thing because (1) it preserves some marker positions
-and (2) it puts less data in the undo list.
+       Finsert_file_contents_internal, 1, 7, 0, /*
+Insert contents of file FILENAME after point; no coding-system frobbing.
+This function is identical to `insert-file-contents' except for the
+handling of the CODESYS and USED-CODESYS arguments under
+XEmacs/Mule. (When Mule support is not present, both functions are
+identical and ignore the CODESYS and USED-CODESYS arguments.)
+
+If support for Mule exists in this Emacs, the file is decoded according
+to CODESYS; if omitted, no conversion happens.  If USED-CODESYS is non-nil,
+it should be a symbol, and the actual coding system that was used for the
+decoding is stored into it.  It will in general be different from CODESYS
+if CODESYS specifies automatic encoding detection or end-of-line detection.
+
+Currently BEG and END refer to byte positions (as opposed to character
+positions), even in Mule. (Fixing this is very difficult.)
 */
-       (filename, visit, beg, end, replace))
+     (filename, visit, beg, end, replace, codesys, used_codesys))
 {
-  /* This function can call lisp */
-  /* #### dmoore - this function hasn't been checked for gc recently */
+  /* This function can GC */
   struct stat st;
   int fd;
   int saverrno = 0;
   Charcount inserted = 0;
   int speccount;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object handler = Qnil, val;
   int total;
   Bufbyte read_buf[READ_BUF_SIZE];
   int mc_count;
   struct buffer *buf = current_buffer;
-  Lisp_Object curbuf;
   int not_regular = 0;
 
   if (buf->base_buffer && ! NILP (visit))
@@ -2919,12 +2907,7 @@
 
   val = Qnil;
 
-  /* #### dmoore - should probably check in various places to see if
-     curbuf was killed and if so signal an error? */
-
-  XSETBUFFER (curbuf, buf);
-
-  GCPRO5 (filename, val, visit, handler, curbuf);
+  GCPRO4 (filename, val, visit, handler);
   
   mc_count = (NILP (replace)) ?
     begin_multiple_change (buf, BUF_PT  (buf), BUF_PT (buf)) :
@@ -2940,11 +2923,16 @@
   handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
   if (!NILP (handler))
     {
-      val = call6 (handler, Qinsert_file_contents, filename,
-		   visit, beg, end, replace);
+      val = call8 (handler, Qinsert_file_contents, filename,
+		   visit, beg, end, replace, codesys, used_codesys);
       goto handled;
     }
 
+#ifdef MULE
+  if (!NILP (used_codesys))
+    CHECK_SYMBOL (used_codesys);
+#endif
+
   if ( (!NILP (beg) || !NILP (end)) && !NILP (visit) )
     error ("Attempt to visit less than an entire file");
   
@@ -3164,6 +3152,12 @@
 
     NGCPRO1 (stream);
     Lstream_set_buffering (XLSTREAM (stream), LSTREAM_BLOCKN_BUFFERED, 65536);
+#ifdef MULE
+    stream = make_decoding_input_stream
+      (XLSTREAM (stream), Fget_coding_system (codesys));
+    Lstream_set_character_mode (XLSTREAM (stream));
+    Lstream_set_buffering (XLSTREAM (stream), LSTREAM_BLOCKN_BUFFERED, 65536);
+#endif
 
     record_unwind_protect (close_stream_unwind, stream);
 
@@ -3193,6 +3187,13 @@
 	inserted  += cc_inserted;
 	cur_point += cc_inserted;
       }
+#ifdef MULE
+    if (!NILP (used_codesys))
+      {
+	Fset (used_codesys,
+	      XCODING_SYSTEM_NAME (decoding_stream_coding_system (XLSTREAM (stream))));
+      }
+#endif
     NUNGCPRO;
   }
 
@@ -3326,27 +3327,18 @@
   return Qnil;
 }
 
-DEFUN ("write-region-internal", Fwrite_region_internal, 3, 6,
+DEFUN ("write-region-internal", Fwrite_region_internal, 3, 7,
        "r\nFWrite region to file: ", /*
-Write current region into specified file.
-When called from a program, takes three arguments:
-START, END and FILENAME.  START and END are buffer positions.
-Optional fourth argument APPEND if non-nil means
-  append to existing file contents (if any).
-Optional fifth argument VISIT if t means
-  set the last-save-file-modtime of buffer to this file's modtime
-  and mark buffer not modified.
-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.
-Kludgy feature: if START is a string, then that string is written
-to the file, instead of any buffer contents, and END is ignored.
+Write current region into specified file; no coding-system frobbing.
+This function is identical to `write-region' except for the handling
+of the CODESYS argument under XEmacs/Mule. (When Mule support is not
+present, both functions are identical and ignore the CODESYS argument.)
+If support for Mule exists in this Emacs, the file is encoded according
+to the value of CODESYS.  If this is nil, no code conversion occurs.
 */
-       (start, end, filename, append, visit, lockname))
+       (start, end, filename, append, visit, lockname, codesys))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   int desc;
   int failure;
   int save_errno = 0;
@@ -3364,17 +3356,15 @@
   struct buffer *given_buffer;
   Bufpos start1, end1;
 
-  /* #### dmoore - if Fexpand_file_name or handlers kill the buffer,
-     we should signal an error rather than blissfully continuing
-     along.  ARGH, this function is going to lose lose lose.  We need
-     to protect the current_buffer from being destroyed, but the
-     multiple return points make this a pain in the butt. */
-
 #ifdef DOS_NT
   int buffer_file_type
     = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
 #endif /* DOS_NT */
 
+#ifdef MULE
+  codesys = Fget_coding_system (codesys);
+#endif /* MULE */
+
   if (current_buffer->base_buffer && ! NILP (visit))
     error ("Cannot do file visiting in an indirect buffer");
 
@@ -3384,7 +3374,6 @@
   {
     Lisp_Object handler;
     struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-
     GCPRO5 (start, filename, visit, visit_file, lockname);
 
     if (visiting_other)
@@ -3407,8 +3396,8 @@
 
     if (!NILP (handler))
       {
-        Lisp_Object val = call6 (handler, Qwrite_region, start, end, 
-                                 filename, append, visit);
+        Lisp_Object val = call7 (handler, Qwrite_region, start, end, 
+                                 filename, append, visit, codesys);
 	if (visiting)
 	  {
 	    BUF_SAVE_MODIFF (current_buffer) = BUF_MODIFF (current_buffer);
@@ -3424,11 +3413,8 @@
 #ifdef CLASH_DETECTION
   if (!auto_saving)
     {
-      Lisp_Object curbuf;
-      struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-
-      XSETBUFFER (curbuf, current_buffer);
-      GCPRO5 (start, filename, visit_file, lockname, curbuf);
+      struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+      GCPRO4 (start, filename, visit_file, lockname);
       lock_file (lockname);
       UNGCPRO;
     }
@@ -3483,8 +3469,7 @@
 	desc = open (fn_data, O_RDWR, 0);
 	if (desc < 0)
 	  desc = creat_copy_attrs ((STRINGP (current_buffer->filename)
-				    ? (char *)
-				    XSTRING_DATA (current_buffer->filename)
+				    ? (char *) XSTRING_DATA (current_buffer->filename)
 				    : 0),
 				   fn_data);
       }
@@ -3611,6 +3596,12 @@
     outstream = make_filedesc_output_stream (desc, 0, -1, 0);
     Lstream_set_buffering (XLSTREAM (outstream),
 			   LSTREAM_BLOCKN_BUFFERED, 65536);
+#ifdef MULE
+    outstream =
+      make_encoding_output_stream ( XLSTREAM (outstream), codesys);
+    Lstream_set_buffering (XLSTREAM (outstream),
+			   LSTREAM_BLOCKN_BUFFERED, 65536);
+#endif
     if (STRINGP (start))
       {
 	instream = make_lisp_string_input_stream (start, 0, -1);
@@ -3861,6 +3852,22 @@
 	nextpos = XINT (tem);
       else
 	nextpos = INT_MAX;
+#ifdef MULE
+      /* If there are annotations left and we have Mule, then we
+	 have to do the I/O one emchar at a time so we can
+	 determine when to insert the annotation. */
+      if (!NILP (*annot))
+	{
+	  Emchar ch;
+	  while (pos != nextpos && (ch = Lstream_get_emchar (instr)) != EOF)
+	    {
+	      if (Lstream_put_emchar (outstr, ch) < 0)
+		return -1;
+	      pos++;
+	    }
+	}
+      else
+#endif
 	{
 	  while (pos != nextpos)
 	    {
@@ -3973,7 +3980,7 @@
 */
        (buf))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   struct buffer *b;
   struct stat st;
   Lisp_Object handler;
@@ -4039,7 +4046,7 @@
 */
        (time_list))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   if (!NILP (time_list))
     {
       time_t the_time;
@@ -4051,10 +4058,11 @@
       Lisp_Object filename;
       struct stat st;
       Lisp_Object handler;
-      struct gcpro gcpro1, gcpro2, gcpro3;
+      struct gcpro gcpro1, gcpro2;
       
-      GCPRO3 (filename, time_list, current_buffer->filename);
-      filename = Fexpand_file_name (current_buffer->filename, Qnil);
+      GCPRO2 (filename, time_list);
+      filename = Fexpand_file_name (current_buffer->filename,
+				    Qnil);
 
       /* If the file name has special constructs in it,
 	 call the corresponding file handler.  */
@@ -4078,7 +4086,7 @@
 */
        (buf, in_time))
 {
-  /* This function can call lisp */
+  /* This function can GC */
   unsigned long time_to_use = 0;
   int set_time_to_use = 0;
   struct stat st;
@@ -4106,16 +4114,16 @@
   if (!set_time_to_use)
     {
       Lisp_Object filename = Qnil;
-      struct gcpro gcpro1;
-      GCPRO1 (filename);
-      /* #### dmoore - do we need to protect XBUFFER (buf)->filename?
-	 What if a ^(*&^&*^*& handler renames a buffer?  I think I'm
-	 getting a headache now. */
+      struct gcpro gcpro1, gcpro2;
+      GCPRO2 (buf, filename);
 
       if (STRINGP (XBUFFER (buf)->filename))
-        filename = Fexpand_file_name (XBUFFER (buf)->filename, Qnil);
+        filename = Fexpand_file_name (XBUFFER (buf)->filename,
+				      Qnil);
       else
         filename = Qnil;
+  
+      UNGCPRO;
 
       if (!NILP (filename) && !NILP (Ffile_exists_p (filename)))
         {
@@ -4123,6 +4131,7 @@
 
 	  /* If the file name has special constructs in it,
 	     call the corresponding file handler.  */
+	  GCPRO1 (filename);
 	  handler = Ffind_file_name_handler (filename, Qset_buffer_modtime);
 	  UNGCPRO;
 	  if (!NILP (handler))
@@ -4137,14 +4146,11 @@
 	    }
         }
       else
-	{
-	  UNGCPRO;
-  	  time_to_use = time ((time_t *) 0);
-	}
+	time_to_use = time ((time_t *) 0);
     }
 
   XBUFFER (buf)->modtime = time_to_use;
-  
+
   return Qnil;
 }
 
@@ -4152,19 +4158,19 @@
 static Lisp_Object
 auto_save_error (Lisp_Object condition_object, Lisp_Object ignored)
 {
-  /* This function can call lisp */
+  /* This function can GC */
   if (gc_in_progress)
     return Qnil;
-  /* Don't try printing an error message after everything is gone! */
-  if (preparing_for_armageddon)
-    return Qnil;
   clear_echo_area (selected_frame (), Qauto_saving, 1);
   Fding (Qt, Qauto_save_error, Qnil);
-  message ("Auto-saving...error for %s", XSTRING_DATA (current_buffer->name));
+  message ("Auto-saving...error for %s",
+	   XSTRING_DATA (current_buffer->name));
   Fsleep_for (make_int (1));
-  message ("Auto-saving...error!for %s", XSTRING_DATA (current_buffer->name));
+  message ("Auto-saving...error!for %s",
+	   XSTRING_DATA (current_buffer->name));
   Fsleep_for (make_int (1));
-  message ("Auto-saving...error for %s", XSTRING_DATA (current_buffer->name));
+  message ("Auto-saving...error for %s",
+	   XSTRING_DATA (current_buffer->name));
   Fsleep_for (make_int (1));
   return Qnil;
 }
@@ -4172,8 +4178,7 @@
 static Lisp_Object
 auto_save_1 (Lisp_Object ignored)
 {
-  /* This function can call lisp */
-  /* #### I think caller is protecting current_buffer? */
+  /* This function can GC */
   struct stat st;
   Lisp_Object fn = current_buffer->filename;
   Lisp_Object a  = current_buffer->auto_save_file_name;
@@ -4193,27 +4198,14 @@
     auto_save_mode_bits = 0600;
 
   return
-    Fwrite_region_internal (Qnil, Qnil, a, Qnil, Qlambda, Qnil);
-}
-
-static Lisp_Object
-auto_save_expand_name_error (Lisp_Object condition_object, Lisp_Object ignored)
-{
-  /* #### this function should spew an error message about not being
-     able to open the .saves file. */
-  return Qnil;
-}
-
-static Lisp_Object
-auto_save_expand_name (Lisp_Object name)
-{
-  struct gcpro gcpro1;
-
-  /* note that caller did NOT gc protect name, so we do it. */
-  /* #### dmoore - this might not be neccessary, if condition_case_1
-     protects it.  but I don't think it does. */
-  GCPRO1 (name);
-  RETURN_UNGCPRO (Fexpand_file_name (name, Qnil));
+    /* !!#### need to deal with this 'escape-quoted everywhere */
+    Fwrite_region_internal (Qnil, Qnil, a, Qnil, Qlambda, Qnil,
+#ifdef MULE
+			    Qescape_quoted
+#else
+			    Qnil
+#endif
+			    );
 }
 
 
@@ -4253,20 +4245,18 @@
 */
        (no_message, current_only))
 {
-  /* This function can call lisp */
-  struct buffer *b;
+  /* This function can GC */
+  struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf;
   int auto_saved = 0;
   int do_handled_files;
   Lisp_Object oquit = Qnil;
   Lisp_Object listfile = Qnil;
-  Lisp_Object old;
   int listdesc = -1;
   int speccount = specpdl_depth ();
-  struct gcpro gcpro1, gcpro2, gcpro3;
-
-  XSETBUFFER (old, current_buffer);
-  GCPRO3 (oquit, listfile, old);
+  struct gcpro gcpro1, gcpro2;
+
+  GCPRO2 (oquit, listfile);
   check_quit (); /* make Vquit_flag accurate */
   /* Ordinarily don't quit within this function,
      but don't make it impossible to quit (in case we get hung in I/O).  */
@@ -4282,10 +4272,7 @@
   run_hook (Qauto_save_hook);
 
   if (GC_STRINGP (Vauto_save_list_file_name))
-    listfile = condition_case_1 (Qt,
-				 auto_save_expand_name,
-				 Vauto_save_list_file_name,
-				 auto_save_expand_name_error, Qnil);
+    listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
 
   /* Make sure auto_saving is reset. */
   record_unwind_protect (do_auto_save_unwind_2, make_int (auto_saving));
@@ -4378,7 +4365,7 @@
 	      if (!auto_saved && GC_STRINGP (listfile) && listdesc < 0)
 		{
 #ifdef DOS_NT
-		  listdesc = open ((char *) XSTRING_DATA (listfile), 
+		  listdesc = open ((char *) XSTRING_DATA (listfile),
 				   O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
 				   S_IREAD | S_IWRITE);
 #else /* not DOS_NT */
@@ -4421,36 +4408,14 @@
 		  write (listdesc, "\n", 1);
 		}
 
-	      /* dmoore - In a bad scenario we've set b=XBUFFER(buf)
-		 based on values in Vbuffer_alist.  auto_save_1 may
-		 cause lisp handlers to run.  Those handlers may kill
-		 the buffer and then GC.  Since the buffer is killed,
-		 it's no longer in Vbuffer_alist so it might get reaped
-		 by the GC.  We also need to protect tail. */
-	      /* #### There is probably a lot of other code which has
-		 pointers into buffers which may get blown away by
-		 handlers. */
-	      {
-		struct gcpro gcpro1, gcpro2;
-		GCPRO2 (buf, tail);
-		condition_case_1 (Qt,
-				  auto_save_1, Qnil,
-				  auto_save_error, Qnil);
-		UNGCPRO;
-	      }
-	      /* Handler killed our saved current-buffer!  Pick any. */
-	      if (!BUFFER_LIVE_P (XBUFFER (old)))
-		XSETBUFFER (old, current_buffer);
-
-	      set_buffer_internal (XBUFFER (old));
+	      condition_case_1 (Qt,
+				auto_save_1, Qnil,
+				auto_save_error, Qnil);
 	      auto_saved++;
-	      
-	      /* Handler killed their own buffer! */
-	      if (!BUFFER_LIVE_P(b))
-		continue;
-
 	      b->auto_save_modified = BUF_MODIFF (b);
 	      b->save_length = make_int (BUF_SIZE (b));
+	      set_buffer_internal (old);
+
 	      EMACS_GET_TIME (after_time);
 	      /* If auto-save took more than 60 seconds,
 		 assume it was an NFS failure that got a timeout.  */