]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
Update docs for `customize-mode'
[gnu-emacs] / lisp / files.el
index 0b011f4c363852fd8dfdbe91ba95cbac7074e31a..1f97fa5f52fba3a67c5c654c620f87e6282362f3 100644 (file)
@@ -1,6 +1,6 @@
 ;;; files.el --- file input and output commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992-2016 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
@@ -55,7 +55,7 @@ FROM with TO when it appears in a directory name.  This replacement is
 done when setting up the default directory of a newly visited file.
 
 FROM is matched against directory names anchored at the first
-character, so it should start with a \"\\\\`\", or, if directory
+character, so it should start with a \"\\\\\\=`\", or, if directory
 names cannot have embedded newlines, with a \"^\".
 
 FROM and TO should be equivalent names, which refer to the
@@ -654,10 +654,14 @@ the value of `default-directory'."
                  'file-directory-p))
 
 \f
-(defun pwd ()
-  "Show the current default directory."
-  (interactive nil)
-  (message "Directory %s" default-directory))
+(defun pwd (&optional insert)
+  "Show the current default directory.
+With prefix argument INSERT, insert the current default directory
+at point instead."
+  (interactive "P")
+  (if insert
+      (insert default-directory)
+    (message "Directory %s" default-directory)))
 
 (defvar cd-path nil
   "Value of the CDPATH environment variable, as a list.
@@ -736,20 +740,27 @@ The path separator is colon in GNU and GNU-like systems."
        (error "No such directory found via CDPATH environment variable"))))
 
 (defsubst directory-name-p (name)
-  "Return non-nil if NAME ends with a slash character."
-  (and (> (length name) 0)
-       (char-equal (aref name (1- (length name))) ?/)))
-
-(defun directory-files-recursively (dir match &optional include-directories)
-  "Return all files under DIR that have file names matching MATCH (a regexp).
+  "Return non-nil if NAME ends with a directory separator character."
+  (let ((len (length name))
+        (lastc ?.))
+    (if (> len 0)
+        (setq lastc (aref name (1- len))))
+    (or (= lastc ?/)
+        (and (memq system-type '(windows-nt ms-dos))
+             (= lastc ?\\)))))
+
+(defun directory-files-recursively (dir regexp &optional include-directories)
+  "Return list of all files under DIR that have file names matching REGEXP.
 This function works recursively.  Files are returned in \"depth first\"
-and alphabetical order.
-If INCLUDE-DIRECTORIES, also include directories that have matching names."
+order, and files from each directory are sorted in alphabetical order.
+Each file name appears in the returned list in its absolute form.
+Optional argument INCLUDE-DIRECTORIES non-nil means also include in the
+output directories whose names match REGEXP."
   (let ((result nil)
        (files nil)
        ;; When DIR is "/", remote file names like "/method:" could
        ;; also be offered.  We shall suppress them.
-       (tramp-mode (and tramp-mode (file-remote-p dir))))
+       (tramp-mode (and tramp-mode (file-remote-p (expand-file-name dir)))))
     (dolist (file (sort (file-name-all-completions "" dir)
                        'string<))
       (unless (member file '("./" "../"))
@@ -760,19 +771,23 @@ If INCLUDE-DIRECTORIES, also include directories that have matching names."
              (unless (file-symlink-p full-file)
                (setq result
                      (nconc result (directory-files-recursively
-                                    full-file match include-directories))))
+                                    full-file regexp include-directories))))
              (when (and include-directories
-                        (string-match match leaf))
+                        (string-match regexp leaf))
                (setq result (nconc result (list full-file)))))
-         (when (string-match match file)
+         (when (string-match regexp file)
            (push (expand-file-name file dir) files)))))
     (nconc result (nreverse files))))
 
+(defvar module-file-suffix)
+
 (defun load-file (file)
   "Load the Lisp file named FILE."
-  ;; This is a case where .elc makes a lot of sense.
+  ;; This is a case where .elc and .so/.dll make a lot of sense.
   (interactive (list (let ((completion-ignored-extensions
-                           (remove ".elc" completion-ignored-extensions)))
+                            (remove module-file-suffix
+                                    (remove ".elc"
+                                            completion-ignored-extensions))))
                       (read-file-name "Load file: " nil nil 'lambda))))
   (load (expand-file-name file) nil nil t))
 
@@ -783,8 +798,8 @@ return nil.
 PATH should be a list of directories to look in, like the lists in
 `exec-path' or `load-path'.
 If SUFFIXES is non-nil, it should be a list of suffixes to append to
-file name when searching.  If SUFFIXES is nil, it is equivalent to '(\"\").
-Use '(\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
+file name when searching.  If SUFFIXES is nil, it is equivalent to (\"\").
+Use (\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
 If non-nil, PREDICATE is used instead of `file-readable-p'.
 
 This function will normally skip directories, so if you want it to find
@@ -1008,6 +1023,7 @@ Return nil if COMMAND is not found anywhere in `exec-path'."
 
 (defun load-library (library)
   "Load the Emacs Lisp library named LIBRARY.
+LIBRARY should be a string.
 This is an interface to the function `load'.  LIBRARY is searched
 for in `load-path', both with and without `load-suffixes' (as
 well as `load-file-rep-suffixes').
@@ -1015,10 +1031,11 @@ well as `load-file-rep-suffixes').
 See Info node `(emacs)Lisp Libraries' for more details.
 See `load-file' for a different interface to `load'."
   (interactive
-   (list (completing-read "Load library: "
-                         (apply-partially 'locate-file-completion-table
-                                           load-path
-                                           (get-load-suffixes)))))
+   (let (completion-ignored-extensions)
+     (list (completing-read "Load library: "
+                            (apply-partially 'locate-file-completion-table
+                                             load-path
+                                             (get-load-suffixes))))))
   (load library))
 
 (defun file-remote-p (file &optional identification connected)
@@ -1053,7 +1070,7 @@ Tip: You can use this expansion of remote identifier components
      to derive a new remote file name from an existing one.  For
      example, if FILE is \"/sudo::/path/to/file\" then
 
-       \(concat \(file-remote-p FILE) \"/bin/sh\")
+       (concat (file-remote-p FILE) \"/bin/sh\")
 
      returns a remote file name for file \"/bin/sh\" that has the
      same remote identifier as FILE but expanded; a name such as
@@ -1088,14 +1105,14 @@ Tip: You can use this expansion of remote identifier components
 
 (defcustom remote-file-name-inhibit-cache 10
   "Whether to use the remote file-name cache for read access.
-When `nil', never expire cached values (caution)
-When `t', never use the cache (safe, but may be slow)
+When nil, never expire cached values (caution)
+When t, never use the cache (safe, but may be slow)
 A number means use cached values for that amount of seconds since caching.
 
 The attributes of remote files are cached for better performance.
 If they are changed outside of Emacs's control, the cached values
 become invalid, and must be reread.  If you are sure that nothing
-other than Emacs changes the files, you can set this variable to `nil'.
+other than Emacs changes the files, you can set this variable to nil.
 
 If a remote file is checked regularly, it might be a good idea to
 let-bind this variable to a value less than the interval between
@@ -1414,8 +1431,10 @@ return value, which may be passed as the REQUIRE-MATCH arg to
 
 (defmacro minibuffer-with-setup-hook (fun &rest body)
   "Temporarily add FUN to `minibuffer-setup-hook' while executing BODY.
-FUN can also be (:append FUN1), in which case FUN1 is appended to
-`minibuffer-setup-hook'.
+
+By default, FUN is prepended to `minibuffer-setup-hook'.  But if FUN is of
+the form `(:append FUN1)', FUN1 will be appended to `minibuffer-setup-hook'
+instead of prepending it.
 
 BODY should use the minibuffer at most once.
 Recursive uses of the minibuffer are unaffected (FUN is not
@@ -1636,7 +1655,9 @@ killed."
   (unless (run-hook-with-args-until-failure 'kill-buffer-query-functions)
     (user-error "Aborted"))
   (and (buffer-modified-p) buffer-file-name
-       (not (yes-or-no-p "Kill and replace the buffer without saving it? "))
+       (not (yes-or-no-p
+             (format-message "Kill and replace buffer `%s' without saving it? "
+                             (buffer-name))))
        (user-error "Aborted"))
   (let ((obuf (current-buffer))
        (ofile buffer-file-name)
@@ -2122,6 +2143,7 @@ Do you want to revisit the file normally now? ")
 \f
 (defun insert-file-contents-literally (filename &optional visit beg end replace)
   "Like `insert-file-contents', but only reads in the file literally.
+See `insert-file-contents' for an explanation of the parameters.
 A buffer may be modified in several ways after reading into the buffer,
 due to Emacs features such as format decoding, character code
 conversion, `find-file-hook', automatic uncompression, etc.
@@ -2277,18 +2299,7 @@ unless NOMODES is non-nil."
       (view-mode-enter))
     (run-hooks 'find-file-hook)))
 
-(defmacro report-errors (format &rest body)
-  "Eval BODY and turn any error into a FORMAT message.
-FORMAT can have a %s escape which will be replaced with the actual error.
-If `debug-on-error' is set, errors are not caught, so that you can
-debug them.
-Avoid using a large BODY since it is duplicated."
-  (declare (debug t) (indent 1))
-  `(if debug-on-error
-       (progn . ,body)
-     (condition-case err
-        (progn . ,body)
-       (error (message ,format (prin1-to-string err))))))
+(define-obsolete-function-alias 'report-errors 'with-demoted-errors "25.1")
 
 (defun normal-mode (&optional find-file)
   "Choose the major mode for this buffer automatically.
@@ -2309,9 +2320,9 @@ in that case, this function acts as if `enable-local-variables' were t."
   (let ((enable-local-variables (or (not find-file) enable-local-variables)))
     ;; FIXME this is less efficient than it could be, since both
     ;; s-a-m and h-l-v may parse the same regions, looking for "mode:".
-    (report-errors "File mode specification error: %s"
+    (with-demoted-errors "File mode specification error: %s"
       (set-auto-mode))
-    (report-errors "File local-variables error: %s"
+    (with-demoted-errors "File local-variables error: %s"
       (hack-local-variables)))
   ;; Turn font lock off and on, to make sure it takes account of
   ;; whatever file local variables are relevant to it.
@@ -2606,7 +2617,7 @@ and `magic-mode-alist', which determines modes based on file contents.")
   "Alist mapping interpreter names to major modes.
 This is used for files whose first lines match `auto-mode-interpreter-regexp'.
 Each element looks like (REGEXP . MODE).
-If \\\\`REGEXP\\\\' matches the name (minus any directory part) of
+If REGEXP matches the entire name (minus any directory part) of
 the interpreter specified in the first line of a script, enable
 major mode MODE.
 
@@ -3310,7 +3321,7 @@ local variables, but directory-local variables may still be applied."
        result)
     (unless mode-only
       (setq file-local-variables-alist nil)
-      (report-errors "Directory-local variables error: %s"
+      (with-demoted-errors "Directory-local variables error: %s"
        ;; Note this is a no-op if enable-local-variables is nil.
        (hack-dir-local-variables)))
     ;; This entire function is basically a no-op if enable-local-variables
@@ -3375,7 +3386,7 @@ local variables, but directory-local variables may still be applied."
                      (error "Local variables entry is missing the prefix"))
                    (end-of-line)
                    ;; Discard the suffix.
-                   (if (looking-back suffix)
+                   (if (looking-back suffix (line-beginning-position))
                        (delete-region (match-beginning 0) (point))
                      (error "Local variables entry is missing the suffix"))
                    (forward-line 1))
@@ -3412,10 +3423,15 @@ local variables, but directory-local variables may still be applied."
                               (unless hack-local-variables--warned-lexical
                                 (setq hack-local-variables--warned-lexical t)
                                 (display-warning
-                                  :warning
-                                  (format "%s: `lexical-binding' at end of file unreliable"
-                                          (file-name-nondirectory
-                                           (or buffer-file-name ""))))))
+                                  'files
+                                  (format-message
+                                   "%s: `lexical-binding' at end of file unreliable"
+                                   (file-name-nondirectory
+                                    ;; We are called from
+                                    ;; 'with-temp-buffer', so we need
+                                    ;; to use 'thisbuf's name in the
+                                    ;; warning message.
+                                    (or (buffer-file-name thisbuf) ""))))))
                              (t
                               (ignore-errors
                                 (push (cons (if (eq var 'eval)
@@ -3548,8 +3564,9 @@ It is dangerous if either of these conditions are met:
             (since (nth 2 o)))
         (message "%s is obsolete%s; %s"
                  var (if since (format " (since %s)" since))
-                 (if (stringp instead) instead
-                   (format "use `%s' instead" instead)))))))
+                 (if (stringp instead)
+                     (substitute-command-keys instead)
+                   (format-message "use `%s' instead" instead)))))))
 
 (defun hack-one-local-variable (var val)
   "Set local variable VAR with value VAL.
@@ -3833,7 +3850,7 @@ This does nothing if either `enable-local-variables' or
              (if (eq (car elt) 'coding)
                   (unless hack-dir-local-variables--warned-coding
                     (setq hack-dir-local-variables--warned-coding t)
-                    (display-warning :warning
+                    (display-warning 'files
                                      "Coding cannot be specified by dir-locals"))
                (unless (memq (car elt) '(eval mode))
                  (setq dir-local-variables-alist
@@ -3855,7 +3872,7 @@ directories."
 However, the mode will not be changed if
 \(1) a local variables list or the `-*-' line specifies a major mode, or
 \(2) the current major mode is a \"special\" mode,
-    not suitable for ordinary files, or
+    not suitable for ordinary files, or
 \(3) the new file name does not particularly specify any mode."
   :type 'boolean
   :group 'editing-basics)
@@ -4021,7 +4038,8 @@ Interactively, confirmation is required unless you supply a prefix argument."
             (not (and (eq (framep-on-display) 'ns)
                       (listp last-nonmenu-event)
                       use-dialog-box))
-            (or (y-or-n-p (format "File `%s' exists; overwrite? " filename))
+            (or (y-or-n-p (format-message
+                            "File `%s' exists; overwrite? " filename))
                 (user-error "Canceled")))
        (set-visited-file-name filename (not confirm))))
   (set-buffer-modified-p t)
@@ -4032,7 +4050,7 @@ Interactively, confirmation is required unless you supply a prefix argument."
   (save-buffer)
   ;; It's likely that the VC status at the new location is different from
   ;; the one at the old location.
-  (vc-find-file-hook))
+  (vc-refresh-state))
 \f
 (defun file-extended-attributes (filename)
   "Return an alist of extended attributes of file FILENAME.
@@ -4046,14 +4064,19 @@ such as SELinux context, list of ACL entries, etc."
   "Set extended attributes of file FILENAME to ATTRIBUTES.
 
 ATTRIBUTES must be an alist of file attributes as returned by
-`file-extended-attributes'."
-  (dolist (elt attributes)
-    (let ((attr (car elt))
-         (val (cdr elt)))
-      (cond ((eq attr 'acl)
-            (set-file-acl filename val))
-           ((eq attr 'selinux-context)
-            (set-file-selinux-context filename val))))))
+`file-extended-attributes'.
+Value is t if the function succeeds in setting the attributes."
+  (let (result rv)
+    (dolist (elt attributes)
+      (let ((attr (car elt))
+           (val (cdr elt)))
+       (cond ((eq attr 'acl)
+               (setq rv (set-file-acl filename val)))
+             ((eq attr 'selinux-context)
+               (setq rv (set-file-selinux-context filename val))))
+        (setq result (or result rv))))
+
+    result))
 \f
 (defun backup-buffer ()
   "Make a backup of the disk file visited by the current buffer, if appropriate.
@@ -4073,80 +4096,75 @@ on the original file; this means that the caller, after saving
 the buffer, should change the extended attributes of the new file
 to agree with the old attributes.
 BACKUPNAME is the backup file name, which is the old file renamed."
-  (if (and make-backup-files (not backup-inhibited)
-          (not buffer-backed-up)
-          (file-exists-p buffer-file-name)
-          (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
-                '(?- ?l)))
-      (let ((real-file-name buffer-file-name)
-           backup-info backupname targets setmodes)
+  (when (and make-backup-files (not backup-inhibited) (not buffer-backed-up))
+    (let ((attributes (file-attributes buffer-file-name)))
+      (when (and attributes (memq (aref (elt attributes 8) 0) '(?- ?l)))
        ;; If specified name is a symbolic link, chase it to the target.
-       ;; Thus we make the backups in the directory where the real file is.
-       (setq real-file-name (file-chase-links real-file-name))
-       (setq backup-info (find-backup-file-name real-file-name)
-             backupname (car backup-info)
-             targets (cdr backup-info))
-       ;; (if (file-directory-p buffer-file-name)
-       ;;     (error "Cannot save buffer in directory %s" buffer-file-name))
-       (if backup-info
-           (condition-case ()
-               (let ((delete-old-versions
-                      ;; If have old versions to maybe delete,
-                      ;; ask the user to confirm now, before doing anything.
-                      ;; But don't actually delete til later.
-                      (and targets
-                           (or (eq delete-old-versions t) (eq delete-old-versions nil))
-                           (or delete-old-versions
-                               (y-or-n-p (format "Delete excess backup versions of %s? "
-                                                 real-file-name)))))
-                     (modes (file-modes buffer-file-name))
-                     (extended-attributes
-                      (file-extended-attributes buffer-file-name)))
-                 ;; Actually write the back up file.
-                 (condition-case ()
-                     (if (or file-precious-flag
-    ;                        (file-symlink-p buffer-file-name)
-                             backup-by-copying
-                             ;; Don't rename a suid or sgid file.
-                             (and modes (< 0 (logand modes #o6000)))
-                             (not (file-writable-p (file-name-directory real-file-name)))
-                             (and backup-by-copying-when-linked
-                                  (> (file-nlinks real-file-name) 1))
-                             (and (or backup-by-copying-when-mismatch
-                                      (integerp backup-by-copying-when-privileged-mismatch))
-                                  (let ((attr (file-attributes real-file-name)))
-                                    (and (or backup-by-copying-when-mismatch
-                                             (and (integerp (nth 2 attr))
-                                                  (integerp backup-by-copying-when-privileged-mismatch)
-                                                  (<= (nth 2 attr) backup-by-copying-when-privileged-mismatch)))
-                                         (not (file-ownership-preserved-p
-                                               real-file-name t))))))
-                         (backup-buffer-copy real-file-name
-                                             backupname modes
-                                             extended-attributes)
-                       ;; rename-file should delete old backup.
-                       (rename-file real-file-name backupname t)
-                       (setq setmodes (list modes extended-attributes
-                                            backupname)))
-                   (file-error
-                    ;; If trouble writing the backup, write it in
-                    ;; .emacs.d/%backup%.
-                    (setq backupname (locate-user-emacs-file "%backup%~"))
-                    (message "Cannot write backup file; backing up in %s"
-                             backupname)
-                    (sleep-for 1)
-                    (backup-buffer-copy real-file-name backupname
-                                        modes extended-attributes)))
-                 (setq buffer-backed-up t)
-                 ;; Now delete the old versions, if desired.
-                 (if delete-old-versions
-                     (while targets
-                       (condition-case ()
-                           (delete-file (car targets))
-                         (file-error nil))
-                       (setq targets (cdr targets))))
-                 setmodes)
-           (file-error nil))))))
+       ;; This makes backups in the directory where the real file is.
+       (let* ((real-file-name (file-chase-links buffer-file-name))
+              (backup-info (find-backup-file-name real-file-name)))
+         (when backup-info
+           (let* ((backupname (car backup-info))
+                  (targets (cdr backup-info))
+                  (old-versions
+                   ;; If have old versions to maybe delete,
+                   ;; ask the user to confirm now, before doing anything.
+                   ;; But don't actually delete til later.
+                   (and targets
+                        (booleanp delete-old-versions)
+                        (or delete-old-versions
+                            (y-or-n-p
+                             (format "Delete excess backup versions of %s? "
+                                     real-file-name)))
+                        targets))
+                  (modes (file-modes buffer-file-name))
+                  (extended-attributes
+                   (file-extended-attributes buffer-file-name))
+                  (copy-when-priv-mismatch
+                   backup-by-copying-when-privileged-mismatch)
+                  (make-copy
+                   (or file-precious-flag backup-by-copying
+                       ;; Don't rename a suid or sgid file.
+                       (and modes (< 0 (logand modes #o6000)))
+                       (not (file-writable-p
+                             (file-name-directory real-file-name)))
+                       (and backup-by-copying-when-linked
+                            (< 1 (file-nlinks real-file-name)))
+                       (and (or backup-by-copying-when-mismatch
+                                (and (integerp copy-when-priv-mismatch)
+                                     (let ((attr (file-attributes
+                                                  real-file-name
+                                                  'integer)))
+                                       (<= (nth 2 attr)
+                                           copy-when-priv-mismatch))))
+                            (not (file-ownership-preserved-p real-file-name
+                                                             t)))))
+                  setmodes)
+             (condition-case ()
+                 (progn
+                   ;; Actually make the backup file.
+                   (if make-copy
+                       (backup-buffer-copy real-file-name backupname
+                                           modes extended-attributes)
+                     ;; rename-file should delete old backup.
+                     (rename-file real-file-name backupname t)
+                     (setq setmodes (list modes extended-attributes
+                                          backupname)))
+                   (setq buffer-backed-up t)
+                   ;; Now delete the old versions, if desired.
+                   (dolist (old-version old-versions)
+                     (delete-file old-version)))
+               (file-error nil))
+             ;; If trouble writing the backup, write it in .emacs.d/%backup%.
+             (when (not buffer-backed-up)
+               (setq backupname (locate-user-emacs-file "%backup%~"))
+               (message "Cannot write backup file; backing up in %s"
+                        backupname)
+               (sleep-for 1)
+               (backup-buffer-copy real-file-name backupname
+                                   modes extended-attributes)
+               (setq buffer-backed-up t))
+             setmodes)))))))
 
 (defun backup-buffer-copy (from-name to-name modes extended-attributes)
   ;; Create temp files with strict access rights.  It's easy to
@@ -4239,8 +4257,8 @@ the group would be preserved too."
 
 (defun file-name-sans-extension (filename)
   "Return FILENAME sans final \"extension\".
-The extension, in a file name, is the part that follows the last `.',
-except that a leading `.', if any, doesn't count."
+The extension, in a file name, is the part that begins with the last `.',
+except that a leading `.' of the file name, if there is one, doesn't count."
   (save-match-data
     (let ((file (file-name-sans-versions (file-name-nondirectory filename)))
          directory)
@@ -4255,15 +4273,16 @@ except that a leading `.', if any, doesn't count."
 
 (defun file-name-extension (filename &optional period)
   "Return FILENAME's final \"extension\".
-The extension, in a file name, is the part that follows the last `.',
-excluding version numbers and backup suffixes,
-except that a leading `.', if any, doesn't count.
+The extension, in a file name, is the part that begins with the last `.',
+excluding version numbers and backup suffixes, except that a leading `.'
+of the file name, if there is one, doesn't count.
 Return nil for extensionless file names such as `foo'.
 Return the empty string for file names such as `foo.'.
 
-If PERIOD is non-nil, then the returned value includes the period
-that delimits the extension, and if FILENAME has no extension,
-the value is \"\"."
+By default, the returned value excludes the period that starts the
+extension, but if the optional argument PERIOD is non-nil, the period
+is included in the value, and in that case, if FILENAME has no
+extension, the value is \"\"."
   (save-match-data
     (let ((file (file-name-sans-versions (file-name-nondirectory filename))))
       (if (and (string-match "\\.[^.]*\\'" file)
@@ -4659,7 +4678,7 @@ See the subroutine `basic-save-buffer' for more information."
              (not noninteractive)
              (not save-silently))
        (message "Saving file %s..." (buffer-file-name)))
-    (basic-save-buffer)
+    (basic-save-buffer (called-interactively-p 'any))
     (and modp (memq arg '(4 64)) (setq buffer-backed-up nil))))
 
 (defun delete-auto-save-file-if-necessary (&optional force)
@@ -4701,14 +4720,14 @@ in such cases.")
 (make-variable-buffer-local 'save-buffer-coding-system)
 (put 'save-buffer-coding-system 'permanent-local t)
 
-(defun basic-save-buffer ()
+(defun basic-save-buffer (&optional called-interactively)
   "Save the current buffer in its visited file, if it has been modified.
 The hooks `write-contents-functions' and `write-file-functions' get a chance
 to do the job of saving; if they do not, then the buffer is saved in
 the visited file in the usual way.
 Before and after saving the buffer, this function runs
 `before-save-hook' and `after-save-hook', respectively."
-  (interactive)
+  (interactive '(called-interactively))
   (save-current-buffer
     ;; In an indirect buffer, save its base buffer instead.
     (if (buffer-base-buffer)
@@ -4731,8 +4750,9 @@ Before and after saving the buffer, this function runs
                         ;; Signal an error if the user specified the name of an
                         ;; existing directory.
                         (error "%s is a directory" filename)
-                      (unless (y-or-n-p (format "File `%s' exists; overwrite? "
-                                                filename))
+                      (unless (y-or-n-p (format-message
+                                         "File `%s' exists; overwrite? "
+                                         filename))
                         (error "Canceled"))))
                 (set-visited-file-name filename)))
          (or (verify-visited-file-modtime (current-buffer))
@@ -4772,7 +4792,8 @@ Before and after saving the buffer, this function runs
                            (expand-file-name buffer-file-name))))
                  (unless (file-exists-p dir)
                    (if (y-or-n-p
-                        (format "Directory `%s' does not exist; create? " dir))
+                        (format-message
+                          "Directory `%s' does not exist; create? " dir))
                        (make-directory dir t)
                      (error "Canceled")))
                  (setq setmodes (basic-save-buffer-1))))
@@ -4800,7 +4821,7 @@ Before and after saving the buffer, this function runs
          (vc-after-save)
          (run-hooks 'after-save-hook))
       (or noninteractive
-          (not (called-interactively-p 'any))
+          (not called-interactively)
           (files--message "(No changes need to be saved)")))))
 
 ;; This does the "real job" of writing a buffer into its visited file
@@ -4845,9 +4866,9 @@ Before and after saving the buffer, this function runs
                    (file-exists-p buffer-file-name)
                    (> (file-nlinks buffer-file-name) 1)
                    (or dir-writable
-                       (error (concat (format
-                                       "Directory %s write-protected; " dir)
-                                      "cannot break hardlink when saving")))))
+                       (error (concat "Directory %s write-protected; "
+                                      "cannot break hardlink when saving")
+                              dir))))
          ;; Write temp name, then rename it.
          ;; This requires write access to the containing dir,
          ;; which is why we don't try it if we don't have that access.
@@ -5055,7 +5076,7 @@ change the additional actions you can take on files."
 \f
 (defun clear-visited-file-modtime ()
   "Clear out records of last mod time of visited file.
-Next attempt to save will certainly not complain of a discrepancy."
+Next attempt to save will not complain of a discrepancy."
   (set-visited-file-modtime 0))
 
 (defun not-modified (&optional arg)
@@ -5215,8 +5236,8 @@ given.  With a prefix argument, TRASH is nil."
      (list dir
           (if (directory-files dir nil directory-files-no-dot-files-regexp)
               (y-or-n-p
-               (format "Directory `%s' is not empty, really %s? "
-                       dir (if trashing "trash" "delete")))
+               (format-message "Directory `%s' is not empty, really %s? "
+                                dir (if trashing "trash" "delete")))
             nil)
           (null current-prefix-arg))))
   ;; If default-directory is a remote directory, make sure we find its
@@ -5278,7 +5299,12 @@ Return nil if DIR is not an existing directory."
              dir  (file-truename dir))
        (let ((ls1 (split-string file "/" t))
              (ls2 (split-string dir  "/" t))
-             (root (if (string-match "\\`/" file) "/" ""))
+             (root
+               (cond
+                ;; A UNC on Windows systems, or a "super-root" on Apollo.
+                ((string-match "\\`//" file) "//")
+                ((string-match "\\`/" file) "/")
+                (t "")))
              (mismatch nil))
          (while (and ls1 ls2 (not mismatch))
            (if (string-equal (car ls1) (car ls2))
@@ -5418,6 +5444,7 @@ This function only handles buffers that are visiting files.
 Non-file buffers need a custom function"
   (and buffer-file-name
        (file-readable-p buffer-file-name)
+       (not (buffer-modified-p (current-buffer)))
        (not (verify-visited-file-modtime (current-buffer)))))
 
 (defvar buffer-stale-function #'buffer-stale--default-function
@@ -6036,6 +6063,7 @@ by `sh' are supported."
 (defun file-expand-wildcards (pattern &optional full)
   "Expand wildcard pattern PATTERN.
 This returns a list of file names which match the pattern.
+Files are sorted in `string<' order.
 
 If PATTERN is written as an absolute file name,
 the values are absolute also.
@@ -6119,7 +6147,7 @@ and `list-directory-verbose-switches'."
 
 PATTERN is assumed to represent a file-name wildcard suitable for the
 underlying filesystem.  For Unix and GNU/Linux, each character from the
-set [ \\t\\n;<>&|()`'\"#$] is quoted with a backslash; for DOS/Windows, all
+set [ \\t\\n;<>&|()\\=`\\='\"#$] is quoted with a backslash; for DOS/Windows, all
 the parts of the pattern which don't include wildcard characters are
 quoted with double quotes.
 
@@ -6194,7 +6222,7 @@ invokes the program specified by `directory-free-space-program'
 and `directory-free-space-args'.  If the system call or program
 is unsuccessful, or if DIR is a remote directory, this function
 returns nil."
-  (unless (file-remote-p dir)
+  (unless (file-remote-p (expand-file-name dir))
     ;; Try to find the number of free blocks.  Non-Posix systems don't
     ;; always have df, but might have an equivalent system call.
     (if (fboundp 'file-system-info)
@@ -6494,7 +6522,7 @@ normally equivalent short `-D' option is just passed on to
                  (setq error-lines (nreverse error-lines))
                  ;; Now read the numeric positions of file names.
                  (goto-char linebeg)
-                 (forward-word 1)
+                 (forward-word-strictly 1)
                  (forward-char 3)
                  (while (< (point) end)
                    (let ((start (insert-directory-adj-pos
@@ -6769,8 +6797,8 @@ If CHAR is in [Xugo], the value is taken from FROM (or 0 if omitted)."
   (cond ((= char ?r) #o0444)
        ((= char ?w) #o0222)
        ((= char ?x) #o0111)
-       ((= char ?s) #o1000)
-       ((= char ?t) #o6000)
+       ((= char ?s) #o6000)
+       ((= char ?t) #o1000)
        ;; Rights relative to the previous file modes.
        ((= char ?X) (if (= (logand from #o111) 0) 0 #o0111))
        ((= char ?u) (let ((uright (logand #o4700 from)))
@@ -6826,7 +6854,7 @@ as in \"og+rX-w\"."
                                  (mapcar 'file-modes-char-to-who
                                          (match-string 1 modes)))))
              (when (= num-who 0)
-               (setq num-who (default-file-modes)))
+               (setq num-who (logior #o7000 (default-file-modes))))
              (setq num-modes
                    (file-modes-rights-to-number (substring modes (match-end 1))
                                                 num-who num-modes)
@@ -6836,7 +6864,7 @@ as in \"og+rX-w\"."
 
 (defun read-file-modes (&optional prompt orig-file)
   "Read file modes in octal or symbolic notation and return its numeric value.
-PROMPT is used as the prompt, default to `File modes (octal or symbolic): '.
+PROMPT is used as the prompt, default to \"File modes (octal or symbolic): \".
 ORIG-FILE is the name of a file on whose mode bits to base returned
 permissions if what user types requests to add, remove, or set permissions
 based on existing mode bits, as in \"og+rX-w\"."