]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/autoload.el
merge trunk
[gnu-emacs] / lisp / emacs-lisp / autoload.el
index 5171d142c248840b9478be8fb2f715ed07c99f41..f8f8d9b00f2bdf6fc413375ed43272fde069462f 100644 (file)
@@ -1,10 +1,10 @@
 ;; autoload.el --- maintain autoloads in loaddefs.el
 
 ;; autoload.el --- maintain autoloads in loaddefs.el
 
-;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1997, 2001-2011  Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Keywords: maint
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Keywords: maint
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
 
 ;; This file is part of GNU Emacs.
 
 (require 'help-fns)                    ;for help-add-fundoc-usage.
 (eval-when-compile (require 'cl))
 
 (require 'help-fns)                    ;for help-add-fundoc-usage.
 (eval-when-compile (require 'cl))
 
-(defvar generated-autoload-file "loaddefs.el"
-   "*File \\[update-file-autoloads] puts autoloads into.
-A `.el' file can set this in its local variables section to make its
-autoloads go somewhere else.  The autoload file is assumed to contain a
-trailer starting with a FormFeed character.")
+(defvar generated-autoload-file nil
+  "File into which to write autoload definitions.
+A Lisp file can set this in its local variables section to make
+its autoloads go somewhere else.
+
+If this is a relative file name, the directory is determined as
+follows:
+ - If a Lisp file defined `generated-autoload-file' as a
+   file-local variable, use its containing directory.
+ - Otherwise use the \"lisp\" subdirectory of `source-directory'.
+
+The autoload file is assumed to contain a trailer starting with a
+FormFeed character.")
 ;;;###autoload
 (put 'generated-autoload-file 'safe-local-variable 'stringp)
 
 ;;;###autoload
 (put 'generated-autoload-file 'safe-local-variable 'stringp)
 
@@ -108,29 +116,48 @@ or macro definition or a defcustom)."
       (let* ((macrop (memq car '(defmacro defmacro*)))
             (name (nth 1 form))
             (args (case car
       (let* ((macrop (memq car '(defmacro defmacro*)))
             (name (nth 1 form))
             (args (case car
-                   ((defun defmacro defun* defmacro*
-                      define-overloadable-function) (nth 2 form))
-                   ((define-skeleton) '(&optional str arg))
-                   ((define-generic-mode define-derived-mode
-                       define-compilation-mode) nil)
-                   (t)))
+                     ((defun defmacro defun* defmacro*
+                        define-overloadable-function) (nth 2 form))
+                     ((define-skeleton) '(&optional str arg))
+                     ((define-generic-mode define-derived-mode
+                        define-compilation-mode) nil)
+                     (t)))
             (body (nthcdr (get car 'doc-string-elt) form))
             (doc (if (stringp (car body)) (pop body))))
        (when (listp args)
          ;; Add the usage form at the end where describe-function-1
          ;; can recover it.
          (setq doc (help-add-fundoc-usage doc args)))
             (body (nthcdr (get car 'doc-string-elt) form))
             (doc (if (stringp (car body)) (pop body))))
        (when (listp args)
          ;; Add the usage form at the end where describe-function-1
          ;; can recover it.
          (setq doc (help-add-fundoc-usage doc args)))
-       ;; `define-generic-mode' quotes the name, so take care of that
-       (list 'autoload (if (listp name) name (list 'quote name)) file doc
-             (or (and (memq car '(define-skeleton define-derived-mode
-                                   define-generic-mode
-                                   easy-mmode-define-global-mode
-                                   define-global-minor-mode
-                                   define-globalized-minor-mode
-                                   easy-mmode-define-minor-mode
-                                   define-minor-mode)) t)
-                 (eq (car-safe (car body)) 'interactive))
-             (if macrop (list 'quote 'macro) nil))))
+        (let ((exp
+               ;; `define-generic-mode' quotes the name, so take care of that
+               (list 'autoload (if (listp name) name (list 'quote name))
+                     file doc
+                     (or (and (memq car '(define-skeleton define-derived-mode
+                                           define-generic-mode
+                                           easy-mmode-define-global-mode
+                                           define-global-minor-mode
+                                           define-globalized-minor-mode
+                                           easy-mmode-define-minor-mode
+                                           define-minor-mode)) t)
+                         (eq (car-safe (car body)) 'interactive))
+                     (if macrop (list 'quote 'macro) nil))))
+          (when macrop
+            ;; Special case to autoload some of the macro's declarations.
+            (let ((decls (nth (if (stringp (nth 3 form)) 4 3) form))
+                  (exps '()))
+              (when (eq (car-safe decls) 'declare)
+                ;; FIXME: We'd like to reuse macro-declaration-function,
+                ;; but we can't since it doesn't return anything.
+                (dolist (decl decls)
+                  (case (car-safe decl)
+                    (indent
+                     (push `(put ',name 'lisp-indent-function ',(cadr decl))
+                           exps))
+                    (doc-string
+                     (push `(put ',name 'doc-string-elt ',(cadr decl)) exps))))
+                (when exps
+                  (setq exp `(progn ,exp ,@exps))))))
+          exp)))
 
      ;; For defclass forms, use `eieio-defclass-autoload'.
      ((eq car 'defclass)
 
      ;; For defclass forms, use `eieio-defclass-autoload'.
      ((eq car 'defclass)
@@ -171,6 +198,15 @@ or macro definition or a defcustom)."
 ;; the doc-string in FORM.
 ;; Those properties are now set in lisp-mode.el.
 
 ;; the doc-string in FORM.
 ;; Those properties are now set in lisp-mode.el.
 
+(defun autoload-find-generated-file ()
+  "Visit the autoload file for the current buffer, and return its buffer.
+If a buffer is visiting the desired autoload file, return it."
+  (let ((enable-local-variables :safe))
+    ;; We used to use `raw-text' to read this file, but this causes
+    ;; problems when the file contains non-ASCII characters.
+    (find-file-noselect
+     (autoload-ensure-default-file (autoload-generated-file)))))
+
 (defun autoload-generated-file ()
   (expand-file-name generated-autoload-file
                     ;; File-local settings of generated-autoload-file should
 (defun autoload-generated-file ()
   (expand-file-name generated-autoload-file
                     ;; File-local settings of generated-autoload-file should
@@ -258,14 +294,17 @@ put the output in."
 TYPE (default \"autoloads\") is a string stating the type of
 information contained in FILE.  If FEATURE is non-nil, FILE
 will provide a feature.  FEATURE may be a string naming the
 TYPE (default \"autoloads\") is a string stating the type of
 information contained in FILE.  If FEATURE is non-nil, FILE
 will provide a feature.  FEATURE may be a string naming the
-feature, otherwise it will be based on FILE's name."
+feature, otherwise it will be based on FILE's name.
+
+At present, a feature is in fact always provided, but this should
+not be relied upon."
   (let ((basename (file-name-nondirectory file)))
     (concat ";;; " basename
            " --- automatically extracted " (or type "autoloads") "\n"
            ";;\n"
            ";;; Code:\n\n"
            "\f\n"
   (let ((basename (file-name-nondirectory file)))
     (concat ";;; " basename
            " --- automatically extracted " (or type "autoloads") "\n"
            ";;\n"
            ";;; Code:\n\n"
            "\f\n"
-           ;; This is used outside of autoload.el.
+           ;; This is used outside of autoload.el, eg cus-dep, finder.
            "(provide '"
            (if (stringp feature)
                feature
            "(provide '"
            (if (stringp feature)
                feature
@@ -324,7 +363,29 @@ which lists the file name and which functions are in it, etc."
   "File local variable to prevent scanning this file for autoload cookies.")
 
 (defun autoload-file-load-name (file)
   "File local variable to prevent scanning this file for autoload cookies.")
 
 (defun autoload-file-load-name (file)
-  (let ((name (file-name-nondirectory file)))
+  "Compute the name that will be used to load FILE."
+  ;; OUTFILE should be the name of the global loaddefs.el file, which
+  ;; is expected to be at the root directory of the files we're
+  ;; scanning for autoloads and will be in the `load-path'.
+  (let* ((outfile (default-value 'generated-autoload-file))
+         (name (file-relative-name file (file-name-directory outfile)))
+         (names '())
+         (dir (file-name-directory outfile)))
+    ;; If `name' has directory components, only keep the
+    ;; last few that are really needed.
+    (while name
+      (setq name (directory-file-name name))
+      (push (file-name-nondirectory name) names)
+      (setq name (file-name-directory name)))
+    (while (not name)
+      (cond
+       ((null (cdr names)) (setq name (car names)))
+       ((file-exists-p (expand-file-name "subdirs.el" dir))
+        ;; FIXME: here we only check the existence of subdirs.el,
+        ;; without checking its content.  This makes it generate wrong load
+        ;; names for cases like lisp/term which is not added to load-path.
+        (setq dir (expand-file-name (pop names) dir)))
+       (t (setq name (mapconcat 'identity names "/")))))
     (if (string-match "\\.elc?\\(\\.\\|\\'\\)" name)
         (substring name 0 (match-beginning 0))
       name)))
     (if (string-match "\\.elc?\\(\\.\\|\\'\\)" name)
         (substring name 0 (match-beginning 0))
       name)))
@@ -337,7 +398,10 @@ If FILE is being visited in a buffer, the contents of the buffer
 are used.
 Return non-nil in the case where no autoloads were added at point."
   (interactive "fGenerate autoloads for file: ")
 are used.
 Return non-nil in the case where no autoloads were added at point."
   (interactive "fGenerate autoloads for file: ")
-  (autoload-generate-file-autoloads file (current-buffer)))
+  (let ((generated-autoload-file buffer-file-name))
+    (autoload-generate-file-autoloads file (current-buffer))))
+
+(defvar print-readably)
 
 ;; When called from `generate-file-autoloads' we should ignore
 ;; `generated-autoload-file' altogether.  When called from
 
 ;; When called from `generate-file-autoloads' we should ignore
 ;; `generated-autoload-file' altogether.  When called from
@@ -369,11 +433,8 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
           (visited (get-file-buffer file))
           (otherbuf nil)
           (absfile (expand-file-name file))
           (visited (get-file-buffer file))
           (otherbuf nil)
           (absfile (expand-file-name file))
-          relfile
           ;; nil until we found a cookie.
           ;; nil until we found a cookie.
-          output-start)
-      (if (member absfile autoload-excludes)
-         (message "Generating autoloads for %s...skipped" file)
+          output-start ostart)
       (with-current-buffer (or visited
                                ;; It is faster to avoid visiting the file.
                                (autoload-find-file file))
       (with-current-buffer (or visited
                                ;; It is faster to avoid visiting the file.
                                (autoload-find-file file))
@@ -383,7 +444,10 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
          (setq load-name
                (if (stringp generated-autoload-load-name)
                    generated-autoload-load-name
          (setq load-name
                (if (stringp generated-autoload-load-name)
                    generated-autoload-load-name
-                 (autoload-file-load-name file)))
+                 (autoload-file-load-name absfile)))
+          (when (and outfile
+                     (not (equal outfile (autoload-generated-file))))
+            (setq otherbuf t))
           (save-excursion
             (save-restriction
               (widen)
           (save-excursion
             (save-restriction
               (widen)
@@ -394,26 +458,22 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
                  ((looking-at (regexp-quote generate-autoload-cookie))
                   ;; If not done yet, figure out where to insert this text.
                   (unless output-start
                  ((looking-at (regexp-quote generate-autoload-cookie))
                   ;; If not done yet, figure out where to insert this text.
                   (unless output-start
-                    (when (and outfile
-                               (not (equal outfile (autoload-generated-file))))
-                      ;; A file-local setting of autoload-generated-file says
-                      ;; we should ignore OUTBUF.
-                      (setq outbuf nil)
-                      (setq otherbuf t))
-                    (unless outbuf
-                      (setq outbuf (autoload-find-destination absfile))
-                      (unless outbuf
-                        ;; The file has autoload cookies, but they're
-                        ;; already up-to-date.  If OUTFILE is nil, the
-                        ;; entries are in the expected OUTBUF, otherwise
-                        ;; they're elsewhere.
-                        (throw 'done outfile)))
-                    (with-current-buffer outbuf
-                      (setq relfile (file-relative-name absfile))
-                      (setq output-start (point)))
-                    ;; (message "file=%S, relfile=%S, dest=%S"
-                    ;;          file relfile (autoload-generated-file))
-                    )
+                    (let ((outbuf
+                           (or (if otherbuf
+                                   ;; A file-local setting of
+                                   ;; autoload-generated-file says we
+                                   ;; should ignore OUTBUF.
+                                   nil
+                                 outbuf)
+                               (autoload-find-destination absfile load-name)
+                               ;; The file has autoload cookies, but they're
+                               ;; already up-to-date. If OUTFILE is nil, the
+                               ;; entries are in the expected OUTBUF,
+                               ;; otherwise they're elsewhere.
+                               (throw 'done otherbuf))))
+                      (with-current-buffer outbuf
+                        (setq output-start (point-marker)
+                              ostart (point)))))
                   (search-forward generate-autoload-cookie)
                   (skip-chars-forward " \t")
                   (if (eolp)
                   (search-forward generate-autoload-cookie)
                   (skip-chars-forward " \t")
                   (if (eolp)
@@ -425,10 +485,12 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
                             (if autoload
                                 (push (nth 1 form) autoloads-done)
                               (setq autoload form))
                             (if autoload
                                 (push (nth 1 form) autoloads-done)
                               (setq autoload form))
-                            (let ((autoload-print-form-outbuf outbuf))
+                            (let ((autoload-print-form-outbuf
+                                   (marker-buffer output-start)))
                               (autoload-print-form autoload)))
                         (error
                               (autoload-print-form autoload)))
                         (error
-                         (message "Error in %s: %S" file err)))
+                         (message "Autoload cookie error in %s:%s %S"
+                                  file (count-lines (point-min) (point)) err)))
 
                     ;; Copy the rest of the line to the output.
                     (princ (buffer-substring
 
                     ;; Copy the rest of the line to the output.
                     (princ (buffer-substring
@@ -440,7 +502,7 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
                                   (forward-char 1))
                               (point))
                             (progn (forward-line 1) (point)))
                                   (forward-char 1))
                               (point))
                             (progn (forward-line 1) (point)))
-                           outbuf)))
+                           (marker-buffer output-start))))
                  ((looking-at ";")
                   ;; Don't read the comment.
                   (forward-line 1))
                  ((looking-at ";")
                   ;; Don't read the comment.
                   (forward-line 1))
@@ -452,56 +514,68 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
             (let ((secondary-autoloads-file-buf
                    (if (local-variable-p 'generated-autoload-file)
                        (current-buffer))))
             (let ((secondary-autoloads-file-buf
                    (if (local-variable-p 'generated-autoload-file)
                        (current-buffer))))
-              (with-current-buffer outbuf
+              (with-current-buffer (marker-buffer output-start)
                 (save-excursion
                   ;; Insert the section-header line which lists the file name
                   ;; and which functions are in it, etc.
                 (save-excursion
                   ;; Insert the section-header line which lists the file name
                   ;; and which functions are in it, etc.
+                  (assert (= ostart output-start))
                   (goto-char output-start)
                   (goto-char output-start)
-                  (autoload-insert-section-header
-                   outbuf autoloads-done load-name relfile
-                   (if secondary-autoloads-file-buf
-                       ;; MD5 checksums are much better because they do not
-                       ;; change unless the file changes (so they'll be
-                       ;; equal on two different systems and will change
-                       ;; less often than time-stamps, thus leading to fewer
-                       ;; unneeded changes causing spurious conflicts), but
-                       ;; using time-stamps is a very useful optimization,
-                       ;; so we use time-stamps for the main autoloads file
-                       ;; (loaddefs.el) where we have special ways to
-                       ;; circumvent the "random change problem", and MD5
-                       ;; checksum in secondary autoload files where we do
-                       ;; not need the time-stamp optimization because it is
-                       ;; already provided by the primary autoloads file.
-                       (md5 secondary-autoloads-file-buf
-                            ;; We'd really want to just use
-                            ;; `emacs-internal' instead.
-                            nil nil 'emacs-mule-unix)
-                     (nth 5 (file-attributes relfile))))
-                  (insert ";;; Generated autoloads from " relfile "\n"))
+                  (let ((relfile (file-relative-name absfile)))
+                    (autoload-insert-section-header
+                     (marker-buffer output-start)
+                     autoloads-done load-name relfile
+                     (if secondary-autoloads-file-buf
+                         ;; MD5 checksums are much better because they do not
+                         ;; change unless the file changes (so they'll be
+                         ;; equal on two different systems and will change
+                         ;; less often than time-stamps, thus leading to fewer
+                         ;; unneeded changes causing spurious conflicts), but
+                         ;; using time-stamps is a very useful optimization,
+                         ;; so we use time-stamps for the main autoloads file
+                         ;; (loaddefs.el) where we have special ways to
+                         ;; circumvent the "random change problem", and MD5
+                         ;; checksum in secondary autoload files where we do
+                         ;; not need the time-stamp optimization because it is
+                         ;; already provided by the primary autoloads file.
+                         (md5 secondary-autoloads-file-buf
+                              ;; We'd really want to just use
+                              ;; `emacs-internal' instead.
+                              nil nil 'emacs-mule-unix)
+                       (nth 5 (file-attributes relfile))))
+                    (insert ";;; Generated autoloads from " relfile "\n")))
                 (insert generate-autoload-section-trailer))))
           (message "Generating autoloads for %s...done" file))
         (or visited
             ;; We created this buffer, so we should kill it.
                 (insert generate-autoload-section-trailer))))
           (message "Generating autoloads for %s...done" file))
         (or visited
             ;; We created this buffer, so we should kill it.
-            (kill-buffer (current-buffer)))))
-      ;; If the entries were added to some other buffer, then the file
-      ;; doesn't add entries to OUTFILE.
-      (or (not output-start) otherbuf))))
+            (kill-buffer (current-buffer))))
+      (or (not output-start)
+          ;; If the entries were added to some other buffer, then the file
+          ;; doesn't add entries to OUTFILE.
+          otherbuf))))
 \f
 (defun autoload-save-buffers ()
   (while autoload-modified-buffers
     (with-current-buffer (pop autoload-modified-buffers)
 \f
 (defun autoload-save-buffers ()
   (while autoload-modified-buffers
     (with-current-buffer (pop autoload-modified-buffers)
-      (save-buffer))))
+      (let ((version-control 'never))
+       (save-buffer)))))
 
 ;;;###autoload
 
 ;;;###autoload
-(defun update-file-autoloads (file &optional save-after)
-  "Update the autoloads for FILE in `generated-autoload-file'
-\(which FILE might bind in its local variables).
-If SAVE-AFTER is non-nil (which is always, when called interactively),
-save the buffer too.
+(defun update-file-autoloads (file &optional save-after outfile)
+  "Update the autoloads for FILE.
+If prefix arg SAVE-AFTER is non-nil, save the buffer too.
+
+If FILE binds `generated-autoload-file' as a file-local variable,
+autoloads are written into that file.  Otherwise, the autoloads
+file is determined by OUTFILE.  If called interactively, prompt
+for OUTFILE; if called from Lisp with OUTFILE nil, use the
+existing value of `generated-autoload-file'.
 
 Return FILE if there was no autoload cookie in it, else nil."
 
 Return FILE if there was no autoload cookie in it, else nil."
-  (interactive "fUpdate autoloads for file: \np")
-  (let* ((autoload-modified-buffers nil)
+  (interactive (list (read-file-name "Update autoloads for file: ")
+                    current-prefix-arg
+                    (read-file-name "Write autoload definitions to file: ")))
+  (let* ((generated-autoload-file (or outfile generated-autoload-file))
+        (autoload-modified-buffers nil)
          (no-autoloads (autoload-generate-file-autoloads file)))
     (if autoload-modified-buffers
         (if save-after (autoload-save-buffers))
          (no-autoloads (autoload-generate-file-autoloads file)))
     (if autoload-modified-buffers
         (if save-after (autoload-save-buffers))
@@ -509,28 +583,23 @@ Return FILE if there was no autoload cookie in it, else nil."
           (message "Autoload section for %s is up to date." file)))
     (if no-autoloads file)))
 
           (message "Autoload section for %s is up to date." file)))
     (if no-autoloads file)))
 
-(defun autoload-find-destination (file)
+(defun autoload-find-destination (file load-name)
   "Find the destination point of the current buffer's autoloads.
 FILE is the file name of the current buffer.
 Returns a buffer whose point is placed at the requested location.
 Returns nil if the file's autoloads are uptodate, otherwise
 removes any prior now out-of-date autoload entries."
   (catch 'up-to-date
   "Find the destination point of the current buffer's autoloads.
 FILE is the file name of the current buffer.
 Returns a buffer whose point is placed at the requested location.
 Returns nil if the file's autoloads are uptodate, otherwise
 removes any prior now out-of-date autoload entries."
   (catch 'up-to-date
-    (let* ((load-name (autoload-file-load-name file))
-           (buf (current-buffer))
+    (let* ((buf (current-buffer))
            (existing-buffer (if buffer-file-name buf))
            (found nil))
            (existing-buffer (if buffer-file-name buf))
            (found nil))
-      (with-current-buffer
-          ;; We used to use `raw-text' to read this file, but this causes
-          ;; problems when the file contains non-ASCII characters.
-          (find-file-noselect
-           (autoload-ensure-default-file (autoload-generated-file)))
+      (with-current-buffer (autoload-find-generated-file)
         ;; This is to make generated-autoload-file have Unix EOLs, so
         ;; that it is portable to all platforms.
         ;; This is to make generated-autoload-file have Unix EOLs, so
         ;; that it is portable to all platforms.
-        (unless (zerop (coding-system-eol-type buffer-file-coding-system))
-          (set-buffer-file-coding-system 'unix))
+        (or (eq 0 (coding-system-eol-type buffer-file-coding-system))
+           (set-buffer-file-coding-system 'unix))
         (or (> (buffer-size) 0)
         (or (> (buffer-size) 0)
-            (error "Autoloads file %s does not exist" buffer-file-name))
+            (error "Autoloads file %s lacks boilerplate" buffer-file-name))
         (or (file-writable-p buffer-file-name)
             (error "Autoloads file %s is not writable" buffer-file-name))
         (widen)
         (or (file-writable-p buffer-file-name)
             (error "Autoloads file %s is not writable" buffer-file-name))
         (widen)
@@ -583,15 +652,20 @@ removes any prior now out-of-date autoload entries."
 
 ;;;###autoload
 (defun update-directory-autoloads (&rest dirs)
 
 ;;;###autoload
 (defun update-directory-autoloads (&rest dirs)
-  "\
-Update loaddefs.el with all the current autoloads from DIRS, and no old ones.
-This uses `update-file-autoloads' (which see) to do its work.
-In an interactive call, you must give one argument, the name
-of a single directory.  In a call from Lisp, you can supply multiple
+  "Update autoload definitions for Lisp files in the directories DIRS.
+In an interactive call, you must give one argument, the name of a
+single directory.  In a call from Lisp, you can supply multiple
 directories as separate arguments, but this usage is discouraged.
 
 The function does NOT recursively descend into subdirectories of the
 directories as separate arguments, but this usage is discouraged.
 
 The function does NOT recursively descend into subdirectories of the
-directory or directories specified."
+directory or directories specified.
+
+In an interactive call, prompt for a default output file for the
+autoload definitions, and temporarily bind the variable
+`generated-autoload-file' to this value.  When called from Lisp,
+use the existing value of `generated-autoload-file'.  If any Lisp
+file binds `generated-autoload-file' as a file-local variable,
+write its autoloads into the specified file instead."
   (interactive "DUpdate autoloads from directory: ")
   (let* ((files-re (let ((tmp nil))
                     (dolist (suf (get-load-suffixes)
   (interactive "DUpdate autoloads from directory: ")
   (let* ((files-re (let ((tmp nil))
                     (dolist (suf (get-load-suffixes)
@@ -607,13 +681,14 @@ directory or directories specified."
          ;; Files with no autoload cookies or whose autoloads go to other
          ;; files because of file-local autoload-generated-file settings.
         (no-autoloads nil)
          ;; Files with no autoload cookies or whose autoloads go to other
          ;; files because of file-local autoload-generated-file settings.
         (no-autoloads nil)
-         (autoload-modified-buffers nil))
+         (autoload-modified-buffers nil)
+        (generated-autoload-file
+         (if (called-interactively-p 'interactive)
+             (read-file-name "Write autoload definitions to file: ")
+           generated-autoload-file)))
 
 
-    (with-current-buffer
-       (find-file-noselect
-         (autoload-ensure-default-file (autoload-generated-file)))
+    (with-current-buffer (autoload-find-generated-file)
       (save-excursion
       (save-excursion
-
        ;; Canonicalize file names and remove the autoload file itself.
        (setq files (delete (file-relative-name buffer-file-name)
                            (mapcar 'file-relative-name files)))
        ;; Canonicalize file names and remove the autoload file itself.
        (setq files (delete (file-relative-name buffer-file-name)
                            (mapcar 'file-relative-name files)))
@@ -638,7 +713,9 @@ directory or directories specified."
                  ((not (stringp file)))
                  ((or (not (file-exists-p file))
                        ;; Remove duplicates as well, just in case.
                  ((not (stringp file)))
                  ((or (not (file-exists-p file))
                        ;; Remove duplicates as well, just in case.
-                       (member file done))
+                       (member file done)
+                       ;; If the file is actually excluded.
+                       (member (expand-file-name file) autoload-excludes))
                    ;; Remove the obsolete section.
                   (autoload-remove-section (match-beginning 0)))
                  ((not (time-less-p (nth 4 form)
                    ;; Remove the obsolete section.
                   (autoload-remove-section (match-beginning 0)))
                  ((not (time-less-p (nth 4 form)
@@ -648,14 +725,20 @@ directory or directories specified."
                  (t
                    (autoload-remove-section (match-beginning 0))
                    (if (autoload-generate-file-autoloads
                  (t
                    (autoload-remove-section (match-beginning 0))
                    (if (autoload-generate-file-autoloads
+                        ;; Passing `current-buffer' makes it insert at point.
                         file (current-buffer) buffer-file-name)
                        (push file no-autoloads))))
             (push file done)
            (setq files (delete file files)))))
       ;; Elements remaining in FILES have no existing autoload sections yet.
       (dolist (file files)
                         file (current-buffer) buffer-file-name)
                        (push file no-autoloads))))
             (push file done)
            (setq files (delete file files)))))
       ;; Elements remaining in FILES have no existing autoload sections yet.
       (dolist (file files)
-        (if (autoload-generate-file-autoloads file nil buffer-file-name)
-            (push file no-autoloads)))
+        (cond
+         ((member (expand-file-name file) autoload-excludes) nil)
+         ;; Passing nil as second argument forces
+         ;; autoload-generate-file-autoloads to look for the right
+         ;; spot where to insert each autoloads section.
+         ((autoload-generate-file-autoloads file nil buffer-file-name)
+          (push file no-autoloads))))
 
       (when no-autoloads
        ;; Sort them for better readability.
 
       (when no-autoloads
        ;; Sort them for better readability.
@@ -667,7 +750,8 @@ directory or directories specified."
         (current-buffer) nil nil no-autoloads this-time)
        (insert generate-autoload-section-trailer))
 
         (current-buffer) nil nil no-autoloads this-time)
        (insert generate-autoload-section-trailer))
 
-      (save-buffer)
+      (let ((version-control 'never))
+       (save-buffer))
       ;; In case autoload entries were added to other files because of
       ;; file-local autoload-generated-file settings.
       (autoload-save-buffers))))
       ;; In case autoload entries were added to other files because of
       ;; file-local autoload-generated-file settings.
       (autoload-save-buffers))))
@@ -681,7 +765,9 @@ directory or directories specified."
 ;;;###autoload
 (defun batch-update-autoloads ()
   "Update loaddefs.el autoloads in batch mode.
 ;;;###autoload
 (defun batch-update-autoloads ()
   "Update loaddefs.el autoloads in batch mode.
-Calls `update-directory-autoloads' on the command line arguments."
+Calls `update-directory-autoloads' on the command line arguments.
+Definitions are written to `generated-autoload-file' (which
+should be non-nil)."
   ;; For use during the Emacs build process only.
   (unless autoload-excludes
     (let* ((ldir (file-name-directory generated-autoload-file))
   ;; For use during the Emacs build process only.
   (unless autoload-excludes
     (let* ((ldir (file-name-directory generated-autoload-file))
@@ -721,17 +807,18 @@ Calls `update-directory-autoloads' on the command line arguments."
                  (forward-line 1))))
          (with-temp-buffer
            (insert-file-contents mfile)
                  (forward-line 1))))
          (with-temp-buffer
            (insert-file-contents mfile)
-           (when (re-search-forward "^lisp= " nil t)
-             (setq lim (line-end-position))
-             (while (re-search-forward "\\${lispsource}\\([^ ]+\\.el\\)c?\\>"
-                                       lim t)
+           (when (re-search-forward "^shortlisp= " nil t)
+             (while (and (not lim)
+                         (re-search-forward "\\.\\./lisp/\\([^ ]+\\.el\\)c?\\>"
+                                            nil t))
                (push (expand-file-name (match-string 1) ldir)
                (push (expand-file-name (match-string 1) ldir)
-                     autoload-excludes))))))))
+                     autoload-excludes)
+               (skip-chars-forward " \t")
+               (if (eolp) (setq lim t)))))))))
   (let ((args command-line-args-left))
     (setq command-line-args-left nil)
     (apply 'update-directory-autoloads args)))
 
 (provide 'autoload)
 
   (let ((args command-line-args-left))
     (setq command-line-args-left nil)
     (apply 'update-directory-autoloads args)))
 
 (provide 'autoload)
 
-;; arch-tag: 00244766-98f4-4767-bf42-8a22103441c6
 ;;; autoload.el ends here
 ;;; autoload.el ends here