Fix warnings when compiling on MS-Windows with -std=gnu99.
[bpt/emacs.git] / src / fileio.c
index 532ab60..d47d7dd 100644 (file)
@@ -23,14 +23,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <setjmp.h>
 #include <unistd.h>
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
 
-#include <ctype.h>
 #include <errno.h>
 
 #ifdef HAVE_LIBSELINUX
@@ -38,6 +36,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <selinux/context.h>
 #endif
 
+#include <c-ctype.h>
+
 #include "lisp.h"
 #include "intervals.h"
 #include "character.h"
@@ -52,6 +52,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define NOMINMAX 1
 #include <windows.h>
 #include <fcntl.h>
+#include <sys/file.h>
+#include "w32.h"
 #endif /* not WINDOWSNT */
 
 #ifdef MSDOS
@@ -67,12 +69,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
 #endif
 #ifdef WINDOWSNT
-#define IS_DRIVE(x) isalpha ((unsigned char) (x))
+#define IS_DRIVE(x) c_isalpha (x)
 #endif
 /* Need to lower-case the drive letter, or else expanded
    filenames will sometimes compare unequal, because
    `expand-file-name' doesn't always down-case the drive letter.  */
-#define DRIVE_LETTER(x) (tolower ((unsigned char) (x)))
+#define DRIVE_LETTER(x) c_tolower (x)
 #endif
 
 #include "systime.h"
@@ -84,22 +86,18 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "commands.h"
 
-#ifndef FILE_SYSTEM_CASE
-#define FILE_SYSTEM_CASE(filename)  (filename)
-#endif
-
-/* Nonzero during writing of auto-save files.  */
-static int auto_saving;
+/* True during writing of auto-save files.  */
+static bool auto_saving;
 
 /* Nonzero umask during creation of auto-save directories.  */
-static int auto_saving_dir_umask;
+static mode_t auto_saving_dir_umask;
 
 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
    a new file with the same mode as the original.  */
-static int auto_save_mode_bits;
+static mode_t auto_save_mode_bits;
 
 /* Set by auto_save_1 if an error occurred during the last auto-save.  */
-static int auto_save_error_occurred;
+static bool auto_save_error_occurred;
 
 /* The symbol bound to coding-system-for-read when
    insert-file-contents is called for recovering a file.  This is not
@@ -148,10 +146,10 @@ Lisp_Object Qfile_name_history;
 
 static Lisp_Object Qcar_less_than_car;
 
-static int a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
-                    Lisp_Object *, struct coding_system *);
-static int e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
-                   struct coding_system *);
+static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
+                    Lisp_Object *, struct coding_system *);
+static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
+                    struct coding_system *);
 
 \f
 void
@@ -163,8 +161,7 @@ report_file_error (const char *string, Lisp_Object data)
 
   synchronize_system_messages_locale ();
   str = strerror (errorno);
-  errstring = code_convert_string_norecord (make_unibyte_string (str,
-                                                                strlen (str)),
+  errstring = code_convert_string_norecord (build_unibyte_string (str),
                                            Vlocale_coding_system, 0);
 
   while (1)
@@ -334,7 +331,6 @@ Given a Unix syntax file name, returns a string ending in slash.  */)
       return STRINGP (handled_name) ? handled_name : Qnil;
     }
 
-  filename = FILE_SYSTEM_CASE (filename);
 #ifdef DOS_NT
   beg = alloca (SBYTES (filename) + 1);
   memcpy (beg, SSDATA (filename), SBYTES (filename) + 1);
@@ -365,12 +361,12 @@ Given a Unix syntax file name, returns a string ending in slash.  */)
 
       if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
        {
-         strncpy (res, beg, 2);
+         memcpy (res, beg, 2);
          beg += 2;
          r += 2;
        }
 
-      if (getdefdir (toupper ((unsigned char) *beg) - 'A' + 1, r))
+      if (getdefdir (c_toupper (*beg) - 'A' + 1, r))
        {
          if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
            strcat (res, "/");
@@ -600,7 +596,7 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
    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
+   BASE64_P 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
    with long file names, add the pid as a decimal number.
@@ -609,7 +605,7 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
    generated.  */
 
 Lisp_Object
-make_temp_name (Lisp_Object prefix, int base64_p)
+make_temp_name (Lisp_Object prefix, bool base64_p)
 {
   Lisp_Object val;
   int len, clen;
@@ -674,7 +670,6 @@ make_temp_name (Lisp_Object prefix, int base64_p)
 
   while (1)
     {
-      struct stat ignored;
       unsigned num = make_temp_name_count;
 
       p[0] = make_temp_name_tbl[num & 63], num >>= 6;
@@ -686,7 +681,7 @@ make_temp_name (Lisp_Object prefix, int base64_p)
       make_temp_name_count += 25229;
       make_temp_name_count %= 225307;
 
-      if (stat (data, &ignored) < 0)
+      if (!check_existing (data))
        {
          /* We want to return only if errno is ENOENT.  */
          if (errno == ENOENT)
@@ -766,12 +761,12 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
   struct passwd *pw;
 #ifdef DOS_NT
   int drive = 0;
-  int collapse_newdir = 1;
-  int is_escaped = 0;
+  bool collapse_newdir = 1;
+  bool is_escaped = 0;
 #endif /* DOS_NT */
   ptrdiff_t length;
   Lisp_Object handler, result, handled_name;
-  int multibyte;
+  bool multibyte;
   Lisp_Object hdir;
 
   CHECK_STRING (name);
@@ -861,7 +856,6 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
        UNGCPRO;
       }
   }
-  name = FILE_SYSTEM_CASE (name);
   multibyte = STRING_MULTIBYTE (name);
   if (multibyte != STRING_MULTIBYTE (default_directory))
     {
@@ -926,10 +920,9 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
       /* If it turns out that the filename we want to return is just a
         suffix of FILENAME, we don't need to go through and edit
         things; we just need to construct a new string using data
-        starting at the middle of FILENAME.  If we set lose to a
-        non-zero value, that means we've discovered that we can't do
-        that cool trick.  */
-      int lose = 0;
+        starting at the middle of FILENAME.  If we set LOSE, that
+        means we've discovered that we can't do that cool trick.  */
+      bool lose = 0;
       char *p = nm;
 
       while (*p)
@@ -1033,9 +1026,9 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
          memcpy (o, nm, p - nm);
          o [p - nm] = 0;
 
-         BLOCK_INPUT;
+         block_input ();
          pw = (struct passwd *) getpwnam (o + 1);
-         UNBLOCK_INPUT;
+         unblock_input ();
          if (pw)
            {
              newdir = pw->pw_dir;
@@ -1060,7 +1053,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
       if (!IS_DIRECTORY_SEP (nm[0]))
        {
          adir = alloca (MAXPATHLEN + 1);
-         if (!getdefdir (toupper (drive) - 'A' + 1, adir))
+         if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
            adir = NULL;
        }
       if (!adir)
@@ -1136,7 +1129,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
          adir = alloca (MAXPATHLEN + 1);
          if (drive)
            {
-             if (!getdefdir (toupper (drive) - 'A' + 1, adir))
+             if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
                newdir = "/";
            }
          else
@@ -1300,7 +1293,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
     if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
 #endif /* WINDOWSNT */
       {
-       if (!drive) abort ();
+       if (!drive) emacs_abort ();
        target -= 2;
        target[0] = DRIVE_LETTER (drive);
        target[1] = ':';
@@ -1366,7 +1359,6 @@ See also the function `substitute-in-file-name'.")
   ptrdiff_t tlen;
   unsigned char *target;
   struct passwd *pw;
-  int lose;
 
   CHECK_STRING (name);
   nm = SDATA (name);
@@ -1375,12 +1367,11 @@ See also the function `substitute-in-file-name'.")
      If no /./ or /../ we can return right away.  */
   if (nm[0] == '/')
     {
+      bool lose = 0;
       p = nm;
-      lose = 0;
       while (*p)
        {
-         if (p[0] == '/' && p[1] == '/'
-             )
+         if (p[0] == '/' && p[1] == '/')
            nm = p + 1;
          if (p[0] == '/' && p[1] == '~')
            nm = p + 1, lose = 1;
@@ -1422,9 +1413,9 @@ See also the function `substitute-in-file-name'.")
        o[len] = 0;
 
        /* Look up the user name.  */
-       BLOCK_INPUT;
+       block_input ();
        pw = (struct passwd *) getpwnam (o + 1);
-       UNBLOCK_INPUT;
+       unblock_input ();
        if (!pw)
          error ("\"%s\" isn't a registered user", o + 1);
 
@@ -1500,7 +1491,7 @@ See also the function `substitute-in-file-name'.")
 #endif
 \f
 /* If /~ or // appears, discard everything through first slash.  */
-static int
+static bool
 file_name_absolute_p (const char *filename)
 {
   return
@@ -1519,17 +1510,16 @@ search_embedded_absfilename (char *nm, char *endp)
 
   for (p = nm + 1; p < endp; p++)
     {
-      if ((0
-          || IS_DIRECTORY_SEP (p[-1]))
+      if (IS_DIRECTORY_SEP (p[-1])
          && file_name_absolute_p (p)
 #if 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)
 #endif /* not (WINDOWSNT || CYGWIN) */
-             )
+         )
        {
-         for (s = p; *s && (!IS_DIRECTORY_SEP (*s)); s++);
+         for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++);
          if (p[0] == '~' && s > p + 1) /* We've got "/~something/".  */
            {
              char *o = alloca (s - p + 1);
@@ -1540,9 +1530,9 @@ search_embedded_absfilename (char *nm, char *endp)
              /* If we have ~user and `user' exists, discard
                 everything up to ~.  But if `user' does not exist, leave
                 ~user alone, it might be a literal file name.  */
-             BLOCK_INPUT;
+             block_input ();
              pw = getpwnam (o + 1);
-             UNBLOCK_INPUT;
+             unblock_input ();
              if (pw)
                return p;
            }
@@ -1566,13 +1556,11 @@ If `//' appears, everything up to and including the first of
 those `/' is discarded.  */)
   (Lisp_Object filename)
 {
-  char *nm;
-
-  register char *s, *p, *o, *x, *endp;
+  char *nm, *s, *p, *o, *x, *endp;
   char *target = NULL;
   int total = 0;
-  int substituted = 0;
-  int multibyte;
+  bool substituted = 0;
+  bool multibyte;
   char *xnm;
   Lisp_Object handler;
 
@@ -1642,13 +1630,13 @@ those `/' is discarded.  */)
        else
          {
            o = p;
-           while (p != endp && (isalnum (*p) || *p == '_')) p++;
+           while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
            s = p;
          }
 
        /* Copy out the variable name.  */
        target = alloca (s - o + 1);
-       strncpy (target, o, s - o);
+       memcpy (target, o, s - o);
        target[s - o] = 0;
 #ifdef DOS_NT
        strupr (target); /* $home == $HOME etc.  */
@@ -1664,7 +1652,7 @@ those `/' is discarded.  */)
               env variables twice should be acceptable. Note that
               decoding may cause a garbage collect.  */
            Lisp_Object orig, decoded;
-           orig = make_unibyte_string (o, strlen (o));
+           orig = build_unibyte_string (o);
            decoded = DECODE_FILE (orig);
            total += SBYTES (decoded);
            substituted = 1;
@@ -1705,13 +1693,13 @@ those `/' is discarded.  */)
        else
          {
            o = p;
-           while (p != endp && (isalnum (*p) || *p == '_')) p++;
+           while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
            s = p;
          }
 
        /* Copy out the variable name.  */
        target = alloca (s - o + 1);
-       strncpy (target, o, s - o);
+       memcpy (target, o, s - o);
        target[s - o] = 0;
 #ifdef DOS_NT
        strupr (target); /* $home == $HOME etc.  */
@@ -1732,13 +1720,13 @@ those `/' is discarded.  */)
            orig = make_unibyte_string (o, orig_length);
            decoded = DECODE_FILE (orig);
            decoded_length = SBYTES (decoded);
-           strncpy (x, SSDATA (decoded), decoded_length);
+           memcpy (x, SDATA (decoded), decoded_length);
            x += decoded_length;
 
            /* If environment variable needed decoding, return value
               needs to be multibyte.  */
            if (decoded_length != orig_length
-               || strncmp (SSDATA (decoded), o, orig_length))
+               || memcmp (SDATA (decoded), o, orig_length))
              multibyte = 1;
          }
       }
@@ -1746,7 +1734,7 @@ those `/' is discarded.  */)
   *x = 0;
 
   /* If /~ or // appears, discard everything through first slash.  */
-  while ((p = search_embedded_absfilename (xnm, x)))
+  while ((p = search_embedded_absfilename (xnm, x)) != NULL)
     /* This time we do not start over because we've already expanded envvars
        and replaced $$ with $.  Maybe we should start over as well, but we'd
        need to quote some $ to $$ first.  */
@@ -1786,7 +1774,7 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
 }
 \f
 /* Signal an error if the file ABSNAME already exists.
-   If INTERACTIVE is nonzero, ask the user whether to proceed,
+   If INTERACTIVE, ask the user whether to proceed,
    and bypass the error if the user says to go ahead.
    QUERYSTRING is a name for the action that is being considered
    to alter the file.
@@ -1795,13 +1783,14 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
    If the file does not exist, STATPTR->st_mode is set to 0.
    If STATPTR is null, we don't store into it.
 
-   If QUICK is nonzero, we ask for y or n, not yes or no.  */
+   If QUICK, ask for y or n, not yes or no.  */
 
 static void
 barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring,
-                             int interactive, struct stat *statptr, int quick)
+                             bool interactive, struct stat *statptr,
+                             bool quick)
 {
-  register Lisp_Object tem, encoded_filename;
+  Lisp_Object tem, encoded_filename;
   struct stat statbuf;
   struct gcpro gcpro1;
 
@@ -1875,11 +1864,11 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   ptrdiff_t count = SPECPDL_INDEX ();
-  int input_file_statable_p;
+  bool input_file_statable_p;
   Lisp_Object encoded_file, encoded_newname;
 #if HAVE_LIBSELINUX
   security_context_t con;
-  int fail, conlength = 0;
+  int conlength = 0;
 #endif
 
   encoded_file = encoded_newname = Qnil;
@@ -1927,12 +1916,12 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
       DWORD attributes;
       char * filename;
 
-      EMACS_GET_TIME (now);
       filename = SDATA (encoded_newname);
 
       /* Ensure file is writable while its modified time is set.  */
       attributes = GetFileAttributes (filename);
       SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY);
+      now = current_emacs_time ();
       if (set_file_times (-1, filename, now, now))
        {
          /* Restore original attributes.  */
@@ -1994,7 +1983,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
                    S_IREAD | S_IWRITE);
 #else  /* not MSDOS */
   {
-    int new_mask = 0666;
+    mode_t new_mask = 0666;
     if (input_file_statable_p)
       {
        if (!NILP (preserve_uid_gid))
@@ -2024,7 +2013,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
      owner and group.  */
   if (input_file_statable_p)
     {
-      int mode_mask = 07777;
+      mode_t mode_mask = 07777;
       if (!NILP (preserve_uid_gid))
        {
          /* Attempt to change owner and group.  If that doesn't work
@@ -2047,7 +2036,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
   if (conlength > 0)
     {
       /* Set the modified context back to the file.  */
-      fail = fsetfilecon (ofd, con);
+      bool fail = fsetfilecon (ofd, con) != 0;
       /* See http://debbugs.gnu.org/11245 for ENOTSUP.  */
       if (fail && errno != ENOTSUP)
        report_file_error ("Doing fsetfilecon", Fcons (newname, Qnil));
@@ -2179,7 +2168,7 @@ With a prefix argument, TRASH is nil.  */)
 
   encoded_file = ENCODE_FILE (filename);
 
-  if (0 > unlink (SSDATA (encoded_file)))
+  if (unlink (SSDATA (encoded_file)) < 0)
     report_file_error ("Removing old name", list1 (filename));
   return Qnil;
 }
@@ -2190,17 +2179,14 @@ internal_delete_file_1 (Lisp_Object ignore)
   return Qt;
 }
 
-/* Delete file FILENAME, returning 1 if successful and 0 if failed.
+/* Delete file FILENAME.
    This ignores `delete-by-moving-to-trash'.  */
 
-int
+void
 internal_delete_file (Lisp_Object filename)
 {
-  Lisp_Object tem;
-
-  tem = internal_condition_case_2 (Fdelete_file, filename, Qnil,
-                                  Qt, internal_delete_file_1);
-  return NILP (tem);
+  internal_condition_case_2 (Fdelete_file, filename, Qnil,
+                            Qt, internal_delete_file_1);
 }
 \f
 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
@@ -2231,8 +2217,8 @@ This is what happens in interactive use with M-x.  */)
 #endif
       )
     {
-      Lisp_Object fname = NILP (Ffile_directory_p (file))
-       ? file : Fdirectory_file_name (file);
+      Lisp_Object fname = (NILP (Ffile_directory_p (file))
+                          ? file : Fdirectory_file_name (file));
       newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname);
     }
   else
@@ -2260,7 +2246,7 @@ This is what happens in interactive use with M-x.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (newname, "rename to it",
                                  INTEGERP (ok_if_already_exists), 0, 0);
-  if (0 > rename (SSDATA (encoded_file), SSDATA (encoded_newname)))
+  if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
     {
       if (errno == EXDEV)
        {
@@ -2341,7 +2327,7 @@ This is what happens in interactive use with M-x.  */)
                                  INTEGERP (ok_if_already_exists), 0, 0);
 
   unlink (SSDATA (newname));
-  if (0 > link (SSDATA (encoded_file), SSDATA (encoded_newname)))
+  if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
     report_file_error ("Adding new name", list2 (file, newname));
 
   UNGCPRO;
@@ -2398,15 +2384,14 @@ This happens for interactive use with M-x.  */)
       || INTEGERP (ok_if_already_exists))
     barf_or_query_if_file_exists (linkname, "make it a link",
                                  INTEGERP (ok_if_already_exists), 0, 0);
-  if (0 > symlink (SSDATA (encoded_filename),
-                  SSDATA (encoded_linkname)))
+  if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0)
     {
       /* If we didn't complain already, silently delete existing file.  */
       if (errno == EEXIST)
        {
          unlink (SSDATA (encoded_linkname));
-         if (0 <= symlink (SSDATA (encoded_filename),
-                           SSDATA (encoded_linkname)))
+         if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname))
+             >= 0)
            {
              UNGCPRO;
              return Qnil;
@@ -2436,9 +2421,24 @@ On Unix, this is a name starting with a `/' or a `~'.  */)
   return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil;
 }
 \f
-/* Return nonzero if file FILENAME exists and can be executed.  */
+/* Return true if FILENAME exists.  */
+bool
+check_existing (const char *filename)
+{
+#ifdef DOS_NT
+  /* The full emulation of Posix 'stat' is too expensive on
+     DOS/Windows, when all we want to know is whether the file exists.
+     So we use 'access' instead, which is much more lightweight.  */
+  return (access (filename, F_OK) >= 0);
+#else
+  struct stat st;
+  return (stat (filename, &st) >= 0);
+#endif
+}
 
-static int
+/* Return true if file FILENAME exists and can be executed.  */
+
+static bool
 check_executable (char *filename)
 {
 #ifdef DOS_NT
@@ -2458,9 +2458,9 @@ check_executable (char *filename)
 #endif /* not DOS_NT */
 }
 
-/* Return nonzero if file FILENAME exists and can be written.  */
+/* Return true if file FILENAME exists and can be written.  */
 
-static int
+static bool
 check_writable (const char *filename)
 {
 #ifdef MSDOS
@@ -2470,7 +2470,7 @@ check_writable (const char *filename)
   return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
 #else /* not MSDOS */
 #ifdef HAVE_EUIDACCESS
-  int res = (euidaccess (filename, 2) >= 0);
+  bool res = (euidaccess (filename, 2) >= 0);
 #ifdef CYGWIN
   /* euidaccess may have returned failure because Cygwin couldn't
      determine the file's UID or GID; if so, we return success. */
@@ -2503,7 +2503,6 @@ Use `file-symlink-p' to test for such links.  */)
 {
   Lisp_Object absname;
   Lisp_Object handler;
-  struct stat statbuf;
 
   CHECK_STRING (filename);
   absname = Fexpand_file_name (filename, Qnil);
@@ -2516,7 +2515,7 @@ Use `file-symlink-p' to test for such links.  */)
 
   absname = ENCODE_FILE (absname);
 
-  return (stat (SSDATA (absname), &statbuf) >= 0) ? Qt : Qnil;
+  return (check_existing (SSDATA (absname))) ? Qt : Qnil;
 }
 
 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2597,7 +2596,6 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
 {
   Lisp_Object absname, dir, encoded;
   Lisp_Object handler;
-  struct stat statbuf;
 
   CHECK_STRING (filename);
   absname = Fexpand_file_name (filename, Qnil);
@@ -2609,7 +2607,7 @@ 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 (SSDATA (encoded), &statbuf) >= 0)
+  if (check_existing (SSDATA (encoded)))
     return (check_writable (SSDATA (encoded))
            ? Qt : Qnil);
 
@@ -2624,9 +2622,7 @@ 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 (SDATA (dir), &statbuf) < 0)
-    return Qnil;
-  return S_ISDIR (statbuf.st_mode) ? Qt : Qnil;
+  return (access (SDATA (dir), D_OK) < 0) ? Qnil : Qt;
 #else
   return (check_writable (!NILP (dir) ? SSDATA (dir) : "")
          ? Qt : Qnil);
@@ -2738,7 +2734,7 @@ searchable directory.  */)
   (Lisp_Object filename)
 {
   Lisp_Object handler;
-  int tem;
+  bool tem;
   struct gcpro gcpro1;
 
   /* If the file name has special constructs in it,
@@ -2846,9 +2842,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support.  */)
          if (context_range_get (context))
            values[3] = build_string (context_range_get (context));
          context_free (context);
+         freecon (con);
        }
-      if (con)
-       freecon (con);
     }
 #endif
 
@@ -2874,7 +2869,8 @@ compiled with SELinux support.  */)
   Lisp_Object type = CAR_SAFE (CDR_SAFE (CDR_SAFE (context)));
   Lisp_Object range = CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (context))));
   security_context_t con;
-  int fail, conlength;
+  bool fail;
+  int conlength;
   context_t parsed_con;
 #endif
 
@@ -2918,19 +2914,18 @@ compiled with SELinux support.  */)
            }
 
          /* Set the modified context back to the file.  */
-         fail = lsetfilecon (SSDATA (encoded_absname),
-                             context_str (parsed_con));
+         fail = (lsetfilecon (SSDATA (encoded_absname),
+                              context_str (parsed_con))
+                 != 0);
           /* See http://debbugs.gnu.org/11245 for ENOTSUP.  */
          if (fail && errno != ENOTSUP)
            report_file_error ("Doing lsetfilecon", Fcons (absname, Qnil));
 
          context_free (parsed_con);
+         freecon (con);
        }
       else
        report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
-
-      if (con)
-       freecon (con);
     }
 #endif
 
@@ -3010,13 +3005,13 @@ DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
 The value is an integer.  */)
   (void)
 {
-  int realmask;
+  mode_t realmask;
   Lisp_Object value;
 
-  BLOCK_INPUT;
+  block_input ();
   realmask = umask (0);
   umask (realmask);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   XSETINT (value, (~ realmask) & 0777);
   return value;
@@ -3048,7 +3043,7 @@ Use the current time if TIMESTAMP is nil.  TIMESTAMP is in the format of
   {
     if (set_file_times (-1, SSDATA (encoded_absname), t, t))
       {
-#ifdef DOS_NT
+#ifdef MSDOS
         struct stat st;
 
         /* Setting times on a directory always fails.  */
@@ -3148,16 +3143,15 @@ decide_coding_unwind (Lisp_Object unwind_data)
   undo_list = XCAR (unwind_data);
   buffer = XCDR (unwind_data);
 
-  if (current_buffer != XBUFFER (buffer))
-    set_buffer_internal (XBUFFER (buffer));
+  set_buffer_internal (XBUFFER (buffer));
   adjust_markers_for_delete (BEG, BEG_BYTE, Z, Z_BYTE);
   adjust_overlays_for_delete (BEG, Z - BEG);
-  BUF_INTERVALS (current_buffer) = 0;
+  set_buffer_intervals (current_buffer, NULL);
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
 
   /* Now we are safe to change the buffer's multibyteness directly.  */
-  BVAR (current_buffer, enable_multibyte_characters) = multibyte;
-  BVAR (current_buffer, undo_list) = undo_list;
+  bset_enable_multibyte_characters (current_buffer, multibyte);
+  bset_undo_list (current_buffer, undo_list);
 
   return Qnil;
 }
@@ -3207,7 +3201,7 @@ emacs_lseek (int fd, EMACS_INT offset, int whence)
 {
   /* Use "&" rather than "&&" to suppress a bogus GCC warning; see
      <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>.  */
-  if (! ((TYPE_MINIMUM (off_t) <= offset) & (offset <= TYPE_MAXIMUM (off_t))))
+  if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t))))
     {
       errno = EINVAL;
       return -1;
@@ -3219,12 +3213,10 @@ emacs_lseek (int fd, EMACS_INT offset, int whence)
 static EMACS_TIME
 time_error_value (int errnum)
 {
-  EMACS_TIME t;
   int ns = (errnum == ENOENT || errnum == EACCES || errnum == ENOTDIR
            ? NONEXISTENT_MODTIME_NSECS
            : UNKNOWN_MODTIME_NSECS);
-  EMACS_SET_SECS_NSECS (t, 0, ns);
-  return t;
+  return make_emacs_time (0, ns);
 }
 
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
@@ -3255,29 +3247,29 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   struct stat st;
   int file_status;
   EMACS_TIME mtime;
-  register int fd;
+  int fd;
   ptrdiff_t inserted = 0;
-  int nochange = 0;
-  register ptrdiff_t how_much;
+  bool nochange = 0;
+  ptrdiff_t how_much;
   off_t beg_offset, end_offset;
-  register int unprocessed;
+  int unprocessed;
   ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   Lisp_Object handler, val, insval, orig_filename, old_undo;
   Lisp_Object p;
   ptrdiff_t total = 0;
-  int not_regular = 0;
+  bool not_regular = 0;
   int save_errno = 0;
   char read_buf[READ_BUF_SIZE];
   struct coding_system coding;
   char buffer[1 << 14];
-  int replace_handled = 0;
-  int set_coding_system = 0;
+  bool replace_handled = 0;
+  bool set_coding_system = 0;
   Lisp_Object coding_system;
-  int read_quit = 0;
+  bool read_quit = 0;
   Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
-  int we_locked_file = 0;
-  int deferred_remove_unwind_protect = 0;
+  bool we_locked_file = 0;
+  bool deferred_remove_unwind_protect = 0;
 
   if (current_buffer->base_buffer && ! NILP (visit))
     error ("Cannot do file visiting in an indirect buffer");
@@ -3382,7 +3374,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
   if (!NILP (beg))
     {
-      if (! (RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))))
+      if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t)))
        wrong_type_argument (intern ("file-offset"), beg);
       beg_offset = XFASTINT (beg);
     }
@@ -3391,7 +3383,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
   if (!NILP (end))
     {
-      if (! (RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))))
+      if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t)))
        wrong_type_argument (intern ("file-offset"), end);
       end_offset = XFASTINT (end);
     }
@@ -3427,8 +3419,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (beg_offset < likely_end)
        {
-         ptrdiff_t buf_bytes =
-           Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE  : 0);
+         ptrdiff_t buf_bytes
+           Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE  : 0);
          ptrdiff_t buf_growth_max = BUF_BYTES_MAX - buf_bytes;
          off_t likely_growth = likely_end - beg_offset;
          if (buf_growth_max < likely_growth)
@@ -3489,22 +3481,22 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                  Lisp_Object workbuf;
                  struct buffer *buf;
 
-                 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+                 record_unwind_current_buffer ();
 
                  workbuf = Fget_buffer_create (build_string (" *code-converting-work*"));
                  buf = XBUFFER (workbuf);
 
                  delete_all_overlays (buf);
-                 BVAR (buf, directory) = BVAR (current_buffer, directory);
-                 BVAR (buf, read_only) = Qnil;
-                 BVAR (buf, filename) = Qnil;
-                 BVAR (buf, undo_list) = Qt;
+                 bset_directory (buf, BVAR (current_buffer, directory));
+                 bset_read_only (buf, Qnil);
+                 bset_filename (buf, Qnil);
+                 bset_undo_list (buf, Qt);
                  eassert (buf->overlays_before == NULL);
                  eassert (buf->overlays_after == NULL);
 
                  set_buffer_internal (buf);
                  Ferase_buffer ();
-                 BVAR (buf, enable_multibyte_characters) = Qnil;
+                 bset_enable_multibyte_characters (buf, Qnil);
 
                  insert_1_both ((char *) read_buf, nread, nread, 0, 0, 0);
                  TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
@@ -3578,9 +3570,9 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       ptrdiff_t same_at_end = ZV_BYTE;
       ptrdiff_t overlap;
       /* There is still a possibility we will find the need to do code
-        conversion.  If that happens, we set this variable to 1 to
+        conversion.  If that happens, set this variable to
         give up on handling REPLACE in the optimized way.  */
-      int giveup_match_end = 0;
+      bool giveup_match_end = 0;
 
       if (beg_offset != 0)
        {
@@ -3768,7 +3760,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       ptrdiff_t temp;
       ptrdiff_t this = 0;
       ptrdiff_t this_count = SPECPDL_INDEX ();
-      int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
+      bool multibyte
+       = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
       Lisp_Object conversion_buffer;
       struct gcpro gcpro1;
 
@@ -4113,8 +4106,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
          unwind_data = Fcons (BVAR (current_buffer, enable_multibyte_characters),
                               Fcons (BVAR (current_buffer, undo_list),
                                      Fcurrent_buffer ()));
-         BVAR (current_buffer, enable_multibyte_characters) = Qnil;
-         BVAR (current_buffer, undo_list) = Qt;
+         bset_enable_multibyte_characters (current_buffer, Qnil);
+         bset_undo_list (current_buffer, Qt);
          record_unwind_protect (decide_coding_unwind, unwind_data);
 
          if (inserted > 0 && ! NILP (Vset_auto_coding_function))
@@ -4162,7 +4155,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
          && NILP (replace))
        /* Visiting a file with these coding system makes the buffer
           unibyte. */
-       BVAR (current_buffer, enable_multibyte_characters) = Qnil;
+       bset_enable_multibyte_characters (current_buffer, Qnil);
     }
 
   coding.dst_multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
@@ -4205,13 +4198,13 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   if (!NILP (visit))
     {
       if (!EQ (BVAR (current_buffer, undo_list), Qt) && !nochange)
-       BVAR (current_buffer, undo_list) = Qnil;
+       bset_undo_list (current_buffer, Qnil);
 
       if (NILP (handler))
        {
          current_buffer->modtime = mtime;
          current_buffer->modtime_size = st.st_size;
-         BVAR (current_buffer, filename) = orig_filename;
+         bset_filename (current_buffer, orig_filename);
        }
 
       SAVE_MODIFF = MODIFF;
@@ -4256,7 +4249,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       /* Save old undo list and don't record undo for decoding.  */
       old_undo = BVAR (current_buffer, undo_list);
-      BVAR (current_buffer, undo_list) = Qt;
+      bset_undo_list (current_buffer, Qt);
 
       if (NILP (replace))
        {
@@ -4348,7 +4341,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (NILP (visit))
        {
-         BVAR (current_buffer, undo_list) = old_undo;
+         bset_undo_list (current_buffer, old_undo);
          if (CONSP (old_undo) && inserted != old_inserted)
            {
              /* Adjust the last undo record for the size change during
@@ -4363,7 +4356,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       else
        /* If undo_list was Qt before, keep it that way.
           Otherwise start with an empty undo_list.  */
-       BVAR (current_buffer, undo_list) = EQ (old_undo, Qt) ? Qt : Qnil;
+       bset_undo_list (current_buffer, EQ (old_undo, Qt) ? Qt : Qnil);
 
       unbind_to (count1, Qnil);
     }
@@ -4435,8 +4428,8 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
         If it is not set locally, we anyway have to convert EOL
         format if the default value of `buffer-file-coding-system'
         tells that it is not Unix-like (LF only) format.  */
-      int using_default_coding = 0;
-      int force_raw_text = 0;
+      bool using_default_coding = 0;
+      bool force_raw_text = 0;
 
       val = BVAR (current_buffer, buffer_file_coding_system);
       if (NILP (val)
@@ -4545,19 +4538,20 @@ This calls `write-region-annotate-functions' at the start, and
 `write-region-post-annotation-function' at the end.  */)
   (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
 {
-  register int desc;
-  int failure;
+  int desc;
+  bool ok;
   int save_errno = 0;
   const char *fn;
   struct stat st;
+  EMACS_TIME modtime;
   ptrdiff_t count = SPECPDL_INDEX ();
   int count1;
   Lisp_Object handler;
   Lisp_Object visit_file;
   Lisp_Object annotations;
   Lisp_Object encoded_filename;
-  int visiting = (EQ (visit, Qt) || STRINGP (visit));
-  int quietly = !NILP (visit);
+  bool visiting = (EQ (visit, Qt) || STRINGP (visit));
+  bool quietly = !NILP (visit);
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   struct buffer *given_buffer;
   struct coding_system coding;
@@ -4603,7 +4597,7 @@ This calls `write-region-annotate-functions' at the start, and
        {
          SAVE_MODIFF = MODIFF;
          XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
-         BVAR (current_buffer, filename) = visit_file;
+         bset_filename (current_buffer, visit_file);
        }
       UNGCPRO;
       return val;
@@ -4721,37 +4715,27 @@ This calls `write-region-annotate-functions' at the start, and
 
   UNGCPRO;
 
-  failure = 0;
   immediate_quit = 1;
 
   if (STRINGP (start))
-    {
-      failure = 0 > a_write (desc, start, 0, SCHARS (start),
-                            &annotations, &coding);
-      save_errno = errno;
-    }
+    ok = a_write (desc, start, 0, SCHARS (start), &annotations, &coding);
   else if (XINT (start) != XINT (end))
-    {
-      failure = 0 > a_write (desc, Qnil,
-                            XINT (start), XINT (end) - XINT (start),
-                            &annotations, &coding);
-      save_errno = errno;
-    }
+    ok = a_write (desc, Qnil, XINT (start), XINT (end) - XINT (start),
+                 &annotations, &coding);
   else
     {
-      /* If file was empty, still need to write the annotations */
+      /* If file was empty, still need to write the annotations */
       coding.mode |= CODING_MODE_LAST_BLOCK;
-      failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
-      save_errno = errno;
+      ok = a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
     }
+  save_errno = errno;
 
-  if (CODING_REQUIRE_FLUSHING (&coding)
-      && !(coding.mode & CODING_MODE_LAST_BLOCK)
-      && ! failure)
+  if (ok && CODING_REQUIRE_FLUSHING (&coding)
+      && !(coding.mode & CODING_MODE_LAST_BLOCK))
     {
       /* We have to flush out a data. */
       coding.mode |= CODING_MODE_LAST_BLOCK;
-      failure = 0 > e_write (desc, Qnil, 1, 1, &coding);
+      ok = e_write (desc, Qnil, 1, 1, &coding);
       save_errno = errno;
     }
 
@@ -4768,15 +4752,22 @@ This calls `write-region-annotate-functions' at the start, and
         ignore EINVAL which happens when fsync is not supported on this
         file.  */
       if (errno != EINTR && errno != EINVAL)
-       failure = 1, save_errno = errno;
+       ok = 0, save_errno = errno;
     }
 #endif
 
+  modtime = invalid_emacs_time ();
+  if (visiting)
+    {
+      if (fstat (desc, &st) == 0)
+       modtime = get_stat_mtime (&st);
+      else
+       ok = 0, save_errno = errno;
+    }
+
   /* NFS can report a write failure now.  */
   if (emacs_close (desc) < 0)
-    failure = 1, save_errno = errno;
-
-  stat (fn, &st);
+    ok = 0, save_errno = errno;
 
   /* Discard the unwind protect for close_file_unwind.  */
   specpdl_ptr = specpdl + count1;
@@ -4805,13 +4796,13 @@ This calls `write-region-annotate-functions' at the start, and
   /* Do this before reporting IO error
      to avoid a "file has changed on disk" warning on
      next attempt to save.  */
-  if (visiting)
+  if (EMACS_TIME_VALID_P (modtime))
     {
-      current_buffer->modtime = get_stat_mtime (&st);
+      current_buffer->modtime = modtime;
       current_buffer->modtime_size = st.st_size;
     }
 
-  if (failure)
+  if (! ok)
     error ("IO error writing %s: %s", SDATA (filename),
           emacs_strerror (save_errno));
 
@@ -4819,7 +4810,7 @@ This calls `write-region-annotate-functions' at the start, and
     {
       SAVE_MODIFF = MODIFF;
       XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
-      BVAR (current_buffer, filename) = visit_file;
+      bset_filename (current_buffer, visit_file);
       update_mode_lines++;
     }
   else if (quietly)
@@ -4867,7 +4858,8 @@ build_annotations (Lisp_Object start, Lisp_Object end)
   Lisp_Object p, res;
   struct gcpro gcpro1, gcpro2;
   Lisp_Object original_buffer;
-  int i, used_global = 0;
+  int i;
+  bool used_global = 0;
 
   XSETBUFFER (original_buffer, current_buffer);
 
@@ -4947,11 +4939,11 @@ build_annotations (Lisp_Object start, Lisp_Object end)
 
    We modify *ANNOT by discarding elements as we use them up.
 
-   The return value is negative in case of system call failure.  */
+   Return true if successful.  */
 
-static int
+static bool
 a_write (int desc, Lisp_Object string, ptrdiff_t pos,
-        register ptrdiff_t nchars, Lisp_Object *annot,
+        ptrdiff_t nchars, Lisp_Object *annot,
         struct coding_system *coding)
 {
   Lisp_Object tem;
@@ -4973,29 +4965,29 @@ a_write (int desc, Lisp_Object string, ptrdiff_t pos,
       /* Output buffer text up to the next annotation's position.  */
       if (nextpos > pos)
        {
-         if (0 > e_write (desc, string, pos, nextpos, coding))
-           return -1;
+         if (!e_write (desc, string, pos, nextpos, coding))
+           return 0;
          pos = nextpos;
        }
       /* Output the annotation.  */
       tem = Fcdr (Fcar (*annot));
       if (STRINGP (tem))
        {
-         if (0 > e_write (desc, tem, 0, SCHARS (tem), coding))
-           return -1;
+         if (!e_write (desc, tem, 0, SCHARS (tem), coding))
+           return 0;
        }
       *annot = Fcdr (*annot);
     }
-  return 0;
+  return 1;
 }
 
 
 /* Write text in the range START and END into descriptor DESC,
    encoding them with coding system CODING.  If STRING is nil, START
    and END are character positions of the current buffer, else they
-   are indexes to the string STRING.  */
+   are indexes to the string STRING.  Return true if successful.  */
 
-static int
+static bool
 e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
         struct coding_system *coding)
 {
@@ -5056,20 +5048,20 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
 
       if (coding->produced > 0)
        {
-         coding->produced -=
-           emacs_write (desc,
-                        STRINGP (coding->dst_object)
-                        ? SSDATA (coding->dst_object)
-                        : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
-                        coding->produced);
+         coding->produced
+           -= emacs_write (desc,
+                           STRINGP (coding->dst_object)
+                           ? SSDATA (coding->dst_object)
+                           : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
+                           coding->produced);
 
          if (coding->produced)
-           return -1;
+           return 0;
        }
       start += coding->consumed_char;
     }
 
-  return 0;
+  return 1;
 }
 \f
 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
@@ -5084,7 +5076,7 @@ See Info node `(elisp)Modification Time' for more details.  */)
   struct stat st;
   Lisp_Object handler;
   Lisp_Object filename;
-  EMACS_TIME mtime, diff, one_second;
+  EMACS_TIME mtime, diff;
 
   if (NILP (buf))
     b = current_buffer;
@@ -5112,11 +5104,10 @@ See Info node `(elisp)Modification Time' for more details.  */)
   if ((EMACS_TIME_EQ (mtime, b->modtime)
        /* If both exist, accept them if they are off by one second.  */
        || (EMACS_TIME_VALID_P (mtime) && EMACS_TIME_VALID_P (b->modtime)
-          && ((EMACS_TIME_LT (mtime, b->modtime)
-               ? EMACS_SUB_TIME (diff, b->modtime, mtime)
-               : EMACS_SUB_TIME (diff, mtime, b->modtime)),
-              EMACS_SET_SECS_NSECS (one_second, 1, 0),
-              EMACS_TIME_LE (diff, one_second))))
+          && ((diff = (EMACS_TIME_LT (mtime, b->modtime)
+                       ? sub_emacs_time (b->modtime, mtime)
+                       : sub_emacs_time (mtime, b->modtime))),
+              EMACS_TIME_LE (diff, make_emacs_time (1, 0)))))
       && (st.st_size == b->modtime_size
           || b->modtime_size < 0))
     return Qt;
@@ -5129,7 +5120,7 @@ DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
 Next attempt to save will certainly not complain of a discrepancy.  */)
   (void)
 {
-  EMACS_SET_SECS_NSECS (current_buffer->modtime, 0, UNKNOWN_MODTIME_NSECS);
+  current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
   current_buffer->modtime_size = -1;
   return Qnil;
 }
@@ -5210,7 +5201,7 @@ auto_save_error (Lisp_Object error_val)
   msg = Fformat (3, args);
   GCPRO1 (msg);
   nbytes = SBYTES (msg);
-  SAFE_ALLOCA (msgbuf, char *, nbytes);
+  msgbuf = SAFE_ALLOCA (nbytes);
   memcpy (msgbuf, SDATA (msg), nbytes);
 
   for (i = 0; i < 3; ++i)
@@ -5241,8 +5232,8 @@ auto_save_1 (void)
       if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0)
        /* But make sure we can overwrite it later!  */
        auto_save_mode_bits = (st.st_mode | 0600) & 0777;
-      else if ((modes = Ffile_modes (BVAR (current_buffer, filename)),
-               INTEGERP (modes)))
+      else if (modes = Ffile_modes (BVAR (current_buffer, filename)),
+              INTEGERP (modes))
        /* Remote files don't cooperate with stat.  */
        auto_save_mode_bits = (XINT (modes) | 0600) & 0777;
     }
@@ -5261,9 +5252,9 @@ do_auto_save_unwind (Lisp_Object arg)  /* used as unwind-protect function */
   auto_saving = 0;
   if (stream != NULL)
     {
-      BLOCK_INPUT;
+      block_input ();
       fclose (stream);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
   return Qnil;
 }
@@ -5309,13 +5300,13 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
 {
   struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf, hook;
-  int auto_saved = 0;
+  bool auto_saved = 0;
   int do_handled_files;
   Lisp_Object oquit;
   FILE *stream = NULL;
   ptrdiff_t count = SPECPDL_INDEX ();
-  int orig_minibuffer_auto_raise = minibuffer_auto_raise;
-  int old_message_p = 0;
+  bool orig_minibuffer_auto_raise = minibuffer_auto_raise;
+  bool old_message_p = 0;
   struct gcpro gcpro1, gcpro2;
 
   if (max_specpdl_size < specpdl_size + 40)
@@ -5394,7 +5385,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
        if (STRINGP (BVAR (b, auto_save_file_name))
            && stream != NULL && do_handled_files == 0)
          {
-           BLOCK_INPUT;
+           block_input ();
            if (!NILP (BVAR (b, filename)))
              {
                fwrite (SDATA (BVAR (b, filename)), 1,
@@ -5404,7 +5395,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
            fwrite (SDATA (BVAR (b, auto_save_file_name)), 1,
                    SBYTES (BVAR (b, auto_save_file_name)), stream);
            putc ('\n', stream);
-           UNBLOCK_INPUT;
+           unblock_input ();
          }
 
        if (!NILP (current_only)
@@ -5428,9 +5419,8 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
                || NILP (Ffind_file_name_handler (BVAR (b, auto_save_file_name),
                                                  Qwrite_region))))
          {
-           EMACS_TIME before_time, after_time;
-
-           EMACS_GET_TIME (before_time);
+           EMACS_TIME before_time = current_emacs_time ();
+           EMACS_TIME after_time;
 
            /* If we had a failure, don't try again for 20 minutes.  */
            if (b->auto_save_failure_time > 0
@@ -5462,12 +5452,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
            if (!auto_saved && NILP (no_message))
              message1 ("Auto-saving...");
            internal_condition_case (auto_save_1, Qt, auto_save_error);
-           auto_saved++;
+           auto_saved = 1;
            BUF_AUTOSAVE_MODIFF (b) = BUF_MODIFF (b);
            XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
            set_buffer_internal (old);
 
-           EMACS_GET_TIME (after_time);
+           after_time = current_emacs_time ();
 
            /* If auto-save took more than 60 seconds,
               assume it was an NFS failure that got a timeout.  */
@@ -5547,7 +5537,8 @@ The return value is only relevant for a call to `read-file-name' that happens
 before any other event (mouse or keypress) is handled.  */)
   (void)
 {
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) \
+  || defined (HAVE_NS)
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
       && use_dialog_box
       && use_file_dialog
@@ -5647,17 +5638,17 @@ of file names regardless of the current language environment.  */);
   Fput (Qfile_error, Qerror_conditions,
        Fpurecopy (list2 (Qfile_error, Qerror)));
   Fput (Qfile_error, Qerror_message,
-       make_pure_c_string ("File error"));
+       build_pure_c_string ("File error"));
 
   Fput (Qfile_already_exists, Qerror_conditions,
        Fpurecopy (list3 (Qfile_already_exists, Qfile_error, Qerror)));
   Fput (Qfile_already_exists, Qerror_message,
-       make_pure_c_string ("File already exists"));
+       build_pure_c_string ("File already exists"));
 
   Fput (Qfile_date_error, Qerror_conditions,
        Fpurecopy (list3 (Qfile_date_error, Qfile_error, Qerror)));
   Fput (Qfile_date_error, Qerror_message,
-       make_pure_c_string ("Cannot set file date"));
+       build_pure_c_string ("Cannot set file date"));
 
   DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist,
               doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially.