Merge changes from emacs-23 branch
[bpt/emacs.git] / lisp / emacs-lisp / autoload.el
CommitLineData
56eebc29 1;; autoload.el --- maintain autoloads in loaddefs.el
c0274f38 2
acaf905b 3;; Copyright (C) 1991-1997, 2001-2012 Free Software Foundation, Inc.
b578f267 4
5762abec 5;; Author: Roland McGrath <roland@gnu.org>
e9571d2a 6;; Keywords: maint
bd78fa1d 7;; Package: emacs
e5167999 8
b578f267
EN
9;; This file is part of GNU Emacs.
10
d6cba7ae 11;; GNU Emacs is free software: you can redistribute it and/or modify
b578f267 12;; it under the terms of the GNU General Public License as published by
d6cba7ae
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
b578f267
EN
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
d6cba7ae 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
0231f2dc 23
07b3798c 24;;; Commentary:
e41b2db1 25
00ee57f3 26;; This code helps GNU Emacs maintainers keep the loaddefs.el file up to
e41b2db1
ER
27;; date. It interprets magic cookies of the form ";;;###autoload" in
28;; lisp source files in various useful ways. To learn more, read the
29;; source; if you're going to use this, you'd better be able to.
30
e5167999
ER
31;;; Code:
32
b0daab9a 33(require 'lisp-mode) ;for `doc-string-elt' properties.
890df022 34(require 'help-fns) ;for help-add-fundoc-usage.
6826a134 35(eval-when-compile (require 'cl))
b0daab9a 36
9ed7c8cb
CY
37(defvar generated-autoload-file nil
38 "File into which to write autoload definitions.
b7d22a83
CY
39A Lisp file can set this in its local variables section to make
40its autoloads go somewhere else.
41
42If this is a relative file name, the directory is determined as
43follows:
44 - If a Lisp file defined `generated-autoload-file' as a
45 file-local variable, use its containing directory.
46 - Otherwise use the \"lisp\" subdirectory of `source-directory'.
47
48The autoload file is assumed to contain a trailer starting with a
49FormFeed character.")
a25beddb 50;;;###autoload
3b979520 51(put 'generated-autoload-file 'safe-local-variable 'stringp)
0ceb5fe0 52
15120dec
CY
53(defvar generated-autoload-load-name nil
54 "Load name for `autoload' statements generated from autoload cookies.
55If nil, this defaults to the file name, sans extension.")
56;;;###autoload
57(put 'generated-autoload-load-name 'safe-local-variable 'stringp)
58
3b979520
SM
59;; This feels like it should be a defconst, but MH-E sets it to
60;; ";;;###mh-autoload" for the autoloads that are to go into mh-loaddefs.el.
61(defvar generate-autoload-cookie ";;;###autoload"
0ceb5fe0
RS
62 "Magic comment indicating the following form should be autoloaded.
63Used by \\[update-file-autoloads]. This string should be
64meaningless to Lisp (e.g., a comment).
65
66This string is used:
67
3b979520 68\;;;###autoload
0ceb5fe0
RS
69\(defun function-to-be-autoloaded () ...)
70
71If this string appears alone on a line, the following form will be
72read and an autoload made for it. If there is further text on the line,
73that text will be copied verbatim to `generated-autoload-file'.")
74
a0436952
GM
75(defvar autoload-excludes nil
76 "If non-nil, list of absolute file names not to scan for autoloads.")
77
0ceb5fe0 78(defconst generate-autoload-section-header "\f\n;;;### "
2336b6a9 79 "String that marks the form at the start of a new file's autoload section.")
0ceb5fe0
RS
80
81(defconst generate-autoload-section-trailer "\n;;;***\n"
82 "String which indicates the end of the section of autoloads for a file.")
83
2336b6a9
KH
84(defconst generate-autoload-section-continuation ";;;;;; "
85 "String to add on each continuation of the section header form.")
86
1fad2b12
SM
87(defvar autoload-modified-buffers) ;Dynamically scoped var.
88
0231f2dc 89(defun make-autoload (form file)
ceaa3695 90 "Turn FORM into an autoload or defvar for source file FILE.
e8139c11
SM
91Returns nil if FORM is not a special autoload form (i.e. a function definition
92or macro definition or a defcustom)."
93 (let ((car (car-safe form)) expand)
94 (cond
95 ;; For complex cases, try again on the macro-expansion.
1b39b493 96 ((and (memq car '(easy-mmode-define-global-mode define-global-minor-mode
32324290 97 define-globalized-minor-mode
e8139c11
SM
98 easy-mmode-define-minor-mode define-minor-mode))
99 (setq expand (let ((load-file-name file)) (macroexpand form)))
100 (eq (car expand) 'progn)
101 (memq :autoload-end expand))
102 (let ((end (memq :autoload-end expand)))
103 ;; Cut-off anything after the :autoload-end marker.
104 (setcdr end nil)
105 (cons 'progn
106 (mapcar (lambda (form) (make-autoload form file))
107 (cdr expand)))))
108
109 ;; For special function-like operators, use the `autoload' function.
110 ((memq car '(defun define-skeleton defmacro define-derived-mode
c6a3142d
JL
111 define-compilation-mode define-generic-mode
112 easy-mmode-define-global-mode define-global-minor-mode
32324290 113 define-globalized-minor-mode
c6a3142d 114 easy-mmode-define-minor-mode define-minor-mode
15120dec 115 defun* defmacro* define-overloadable-function))
74312ddc 116 (let* ((macrop (memq car '(defmacro defmacro*)))
e8139c11 117 (name (nth 1 form))
6826a134 118 (args (case car
0193499f
SM
119 ((defun defmacro defun* defmacro*
120 define-overloadable-function) (nth 2 form))
121 ((define-skeleton) '(&optional str arg))
122 ((define-generic-mode define-derived-mode
123 define-compilation-mode) nil)
124 (t)))
e8139c11
SM
125 (body (nthcdr (get car 'doc-string-elt) form))
126 (doc (if (stringp (car body)) (pop body))))
890df022
SM
127 (when (listp args)
128 ;; Add the usage form at the end where describe-function-1
129 ;; can recover it.
130 (setq doc (help-add-fundoc-usage doc args)))
0193499f
SM
131 (let ((exp
132 ;; `define-generic-mode' quotes the name, so take care of that
133 (list 'autoload (if (listp name) name (list 'quote name))
134 file doc
135 (or (and (memq car '(define-skeleton define-derived-mode
136 define-generic-mode
137 easy-mmode-define-global-mode
138 define-global-minor-mode
139 define-globalized-minor-mode
140 easy-mmode-define-minor-mode
141 define-minor-mode)) t)
142 (eq (car-safe (car body)) 'interactive))
143 (if macrop (list 'quote 'macro) nil))))
144 (when macrop
145 ;; Special case to autoload some of the macro's declarations.
146 (let ((decls (nth (if (stringp (nth 3 form)) 4 3) form))
147 (exps '()))
ba83908c 148 (when (eq (car-safe decls) 'declare)
0193499f
SM
149 ;; FIXME: We'd like to reuse macro-declaration-function,
150 ;; but we can't since it doesn't return anything.
151 (dolist (decl decls)
152 (case (car-safe decl)
153 (indent
154 (push `(put ',name 'lisp-indent-function ',(cadr decl))
155 exps))
156 (doc-string
157 (push `(put ',name 'doc-string-elt ',(cadr decl)) exps))))
158 (when exps
159 (setq exp `(progn ,exp ,@exps))))))
160 exp)))
e8139c11 161
15120dec
CY
162 ;; For defclass forms, use `eieio-defclass-autoload'.
163 ((eq car 'defclass)
164 (let ((name (nth 1 form))
165 (superclasses (nth 2 form))
166 (doc (nth 4 form)))
167 (list 'eieio-defclass-autoload (list 'quote name)
168 (list 'quote superclasses) file doc)))
169
d49298d9 170 ;; Convert defcustom to less space-consuming data.
e8139c11
SM
171 ((eq car 'defcustom)
172 (let ((varname (car-safe (cdr-safe form)))
173 (init (car-safe (cdr-safe (cdr-safe form))))
174 (doc (car-safe (cdr-safe (cdr-safe (cdr-safe form)))))
d49298d9
MR
175 ;; (rest (cdr-safe (cdr-safe (cdr-safe (cdr-safe form)))))
176 )
177 `(progn
178 (defvar ,varname ,init ,doc)
fb2dd970
SM
179 (custom-autoload ',varname ,file
180 ,(condition-case nil
181 (null (cadr (memq :set form)))
182 (error nil))))))
e8139c11 183
1bddeeed
SM
184 ((eq car 'defgroup)
185 ;; In Emacs this is normally handled separately by cus-dep.el, but for
186 ;; third party packages, it can be convenient to explicitly autoload
187 ;; a group.
188 (let ((groupname (nth 1 form)))
189 `(let ((loads (get ',groupname 'custom-loads)))
190 (if (member ',file loads) nil
191 (put ',groupname 'custom-loads (cons ',file loads))))))
192
e8139c11
SM
193 ;; nil here indicates that this is not a special autoload form.
194 (t nil))))
0231f2dc 195
890df022
SM
196;; Forms which have doc-strings which should be printed specially.
197;; A doc-string-elt property of ELT says that (nth ELT FORM) is
198;; the doc-string in FORM.
199;; Those properties are now set in lisp-mode.el.
fc89daee 200
9ed7c8cb
CY
201(defun autoload-find-generated-file ()
202 "Visit the autoload file for the current buffer, and return its buffer.
203If a buffer is visiting the desired autoload file, return it."
204 (let ((enable-local-variables :safe))
205 ;; We used to use `raw-text' to read this file, but this causes
206 ;; problems when the file contains non-ASCII characters.
207 (find-file-noselect
208 (autoload-ensure-default-file (autoload-generated-file)))))
209
3b979520
SM
210(defun autoload-generated-file ()
211 (expand-file-name generated-autoload-file
438d6bb6
SM
212 ;; File-local settings of generated-autoload-file should
213 ;; be interpreted relative to the file's location,
214 ;; of course.
215 (if (not (local-variable-p 'generated-autoload-file))
216 (expand-file-name "lisp" source-directory))))
0231f2dc 217
72c19d97 218
2336b6a9
KH
219(defun autoload-read-section-header ()
220 "Read a section header form.
221Since continuation lines have been marked as comments,
222we must copy the text of the form and remove those comment
223markers before we call `read'."
224 (save-match-data
225 (let ((beginning (point))
226 string)
227 (forward-line 1)
228 (while (looking-at generate-autoload-section-continuation)
229 (forward-line 1))
230 (setq string (buffer-substring beginning (point)))
231 (with-current-buffer (get-buffer-create " *autoload*")
232 (erase-buffer)
233 (insert string)
234 (goto-char (point-min))
235 (while (search-forward generate-autoload-section-continuation nil t)
236 (replace-match " "))
237 (goto-char (point-min))
238 (read (current-buffer))))))
239
ac644d50
JB
240(defvar autoload-print-form-outbuf nil
241 "Buffer which gets the output of `autoload-print-form'.")
4a3c5b3a 242
a8add29d 243(defun autoload-print-form (form)
4a3c5b3a
RS
244 "Print FORM such that `make-docfile' will find the docstrings.
245The variable `autoload-print-form-outbuf' specifies the buffer to
246put the output in."
a8add29d
SM
247 (cond
248 ;; If the form is a sequence, recurse.
249 ((eq (car form) 'progn) (mapcar 'autoload-print-form (cdr form)))
250 ;; Symbols at the toplevel are meaningless.
251 ((symbolp form) nil)
252 (t
4a3c5b3a
RS
253 (let ((doc-string-elt (get (car-safe form) 'doc-string-elt))
254 (outbuf autoload-print-form-outbuf))
a8add29d
SM
255 (if (and doc-string-elt (stringp (nth doc-string-elt form)))
256 ;; We need to hack the printing because the
257 ;; doc-string must be printed specially for
258 ;; make-docfile (sigh).
259 (let* ((p (nthcdr (1- doc-string-elt) form))
260 (elt (cdr p)))
261 (setcdr p nil)
262 (princ "\n(" outbuf)
263 (let ((print-escape-newlines t)
9d8563ca 264 (print-quoted t)
a8add29d 265 (print-escape-nonascii t))
7dab57b6
RS
266 (dolist (elt form)
267 (prin1 elt outbuf)
268 (princ " " outbuf)))
a8add29d
SM
269 (princ "\"\\\n" outbuf)
270 (let ((begin (with-current-buffer outbuf (point))))
271 (princ (substring (prin1-to-string (car elt)) 1)
272 outbuf)
273 ;; Insert a backslash before each ( that
274 ;; appears at the beginning of a line in
275 ;; the doc string.
276 (with-current-buffer outbuf
277 (save-excursion
890df022 278 (while (re-search-backward "\n[[(]" begin t)
a8add29d
SM
279 (forward-char 1)
280 (insert "\\"))))
281 (if (null (cdr elt))
282 (princ ")" outbuf)
283 (princ " " outbuf)
284 (princ (substring (prin1-to-string (cdr elt)) 1)
285 outbuf))
286 (terpri outbuf)))
287 (let ((print-escape-newlines t)
9d8563ca 288 (print-quoted t)
a8add29d
SM
289 (print-escape-nonascii t))
290 (print form outbuf)))))))
291
4ad6a5e7 292(defun autoload-rubric (file &optional type feature)
a98f63d4
GM
293 "Return a string giving the appropriate autoload rubric for FILE.
294TYPE (default \"autoloads\") is a string stating the type of
4ad6a5e7
GM
295information contained in FILE. If FEATURE is non-nil, FILE
296will provide a feature. FEATURE may be a string naming the
c70815f1
GM
297feature, otherwise it will be based on FILE's name.
298
299At present, a feature is in fact always provided, but this should
300not be relied upon."
a98f63d4
GM
301 (let ((basename (file-name-nondirectory file)))
302 (concat ";;; " basename
303 " --- automatically extracted " (or type "autoloads") "\n"
304 ";;\n"
305 ";;; Code:\n\n"
306 "\f\n"
c70815f1 307 ;; This is used outside of autoload.el, eg cus-dep, finder.
0ad57dfd
CY
308 "(provide '"
309 (if (stringp feature)
310 feature
311 (file-name-sans-extension basename))
312 ")\n"
a98f63d4
GM
313 ";; Local Variables:\n"
314 ";; version-control: never\n"
315 ";; no-byte-compile: t\n"
316 ";; no-update-autoloads: t\n"
e542c600 317 ";; coding: utf-8\n"
a98f63d4
GM
318 ";; End:\n"
319 ";;; " basename
320 " ends here\n")))
321
a273d3e0
GM
322(defun autoload-ensure-default-file (file)
323 "Make sure that the autoload file FILE exists and if not create it."
324 (unless (file-exists-p file)
a98f63d4 325 (write-region (autoload-rubric file) nil file))
a273d3e0
GM
326 file)
327
328(defun autoload-insert-section-header (outbuf autoloads load-name file time)
329 "Insert the section-header line,
330which lists the file name and which functions are in it, etc."
331 (insert generate-autoload-section-header)
1fad2b12 332 (prin1 (list 'autoloads autoloads load-name file time)
a273d3e0
GM
333 outbuf)
334 (terpri outbuf)
335 ;; Break that line at spaces, to avoid very long lines.
336 ;; Make each sub-line into a comment.
337 (with-current-buffer outbuf
338 (save-excursion
339 (forward-line -1)
340 (while (not (eolp))
341 (move-to-column 64)
342 (skip-chars-forward "^ \n")
343 (or (eolp)
344 (insert "\n" generate-autoload-section-continuation))))))
345
69135525
SM
346(defun autoload-find-file (file)
347 "Fetch file and put it in a temp buffer. Return the buffer."
348 ;; It is faster to avoid visiting the file.
3b979520 349 (setq file (expand-file-name file))
69135525
SM
350 (with-current-buffer (get-buffer-create " *autoload-file*")
351 (kill-all-local-variables)
352 (erase-buffer)
353 (setq buffer-undo-list t
354 buffer-read-only nil)
355 (emacs-lisp-mode)
3b979520 356 (setq default-directory (file-name-directory file))
69135525
SM
357 (insert-file-contents file nil)
358 (let ((enable-local-variables :safe))
359 (hack-local-variables))
360 (current-buffer)))
361
b17b8839
SM
362(defvar no-update-autoloads nil
363 "File local variable to prevent scanning this file for autoload cookies.")
364
3b979520 365(defun autoload-file-load-name (file)
f8ea0098
SM
366 "Compute the name that will be used to load FILE."
367 ;; OUTFILE should be the name of the global loaddefs.el file, which
368 ;; is expected to be at the root directory of the files we're
369 ;; scanning for autoloads and will be in the `load-path'.
370 (let* ((outfile (default-value 'generated-autoload-file))
371 (name (file-relative-name file (file-name-directory outfile)))
372 (names '())
373 (dir (file-name-directory outfile)))
374 ;; If `name' has directory components, only keep the
375 ;; last few that are really needed.
376 (while name
377 (setq name (directory-file-name name))
378 (push (file-name-nondirectory name) names)
379 (setq name (file-name-directory name)))
380 (while (not name)
381 (cond
382 ((null (cdr names)) (setq name (car names)))
383 ((file-exists-p (expand-file-name "subdirs.el" dir))
384 ;; FIXME: here we only check the existence of subdirs.el,
385 ;; without checking its content. This makes it generate wrong load
386 ;; names for cases like lisp/term which is not added to load-path.
387 (setq dir (expand-file-name (pop names) dir)))
388 (t (setq name (mapconcat 'identity names "/")))))
3b979520
SM
389 (if (string-match "\\.elc?\\(\\.\\|\\'\\)" name)
390 (substring name 0 (match-beginning 0))
391 name)))
392
0231f2dc
JB
393(defun generate-file-autoloads (file)
394 "Insert at point a loaddefs autoload section for FILE.
b17b8839 395Autoloads are generated for defuns and defmacros in FILE
da8826b4 396marked by `generate-autoload-cookie' (which see).
0231f2dc 397If FILE is being visited in a buffer, the contents of the buffer
b17b8839
SM
398are used.
399Return non-nil in the case where no autoloads were added at point."
0231f2dc 400 (interactive "fGenerate autoloads for file: ")
9ed7c8cb
CY
401 (let ((generated-autoload-file buffer-file-name))
402 (autoload-generate-file-autoloads file (current-buffer))))
ceea9b18 403
f8ea0098
SM
404(defvar print-readably)
405
438d6bb6
SM
406;; When called from `generate-file-autoloads' we should ignore
407;; `generated-autoload-file' altogether. When called from
408;; `update-file-autoloads' we don't know `outbuf'. And when called from
409;; `update-directory-autoloads' it's in between: we know the default
410;; `outbuf' but we should obey any file-local setting of
411;; `generated-autoload-file'.
412(defun autoload-generate-file-autoloads (file &optional outbuf outfile)
ceea9b18
SM
413 "Insert an autoload section for FILE in the appropriate buffer.
414Autoloads are generated for defuns and defmacros in FILE
415marked by `generate-autoload-cookie' (which see).
416If FILE is being visited in a buffer, the contents of the buffer are used.
438d6bb6 417OUTBUF is the buffer in which the autoload statements should be inserted.
986c5ad5 418If OUTBUF is nil, it will be determined by `autoload-generated-file'.
e66466a6 419
438d6bb6
SM
420If provided, OUTFILE is expected to be the file name of OUTBUF.
421If OUTFILE is non-nil and FILE specifies a `generated-autoload-file'
422different from OUTFILE, then OUTBUF is ignored.
423
1603d855 424Return non-nil if and only if FILE adds no autoloads to OUTFILE
438d6bb6 425\(or OUTBUF if OUTFILE is nil)."
1fad2b12
SM
426 (catch 'done
427 (let ((autoloads-done '())
15120dec 428 load-name
1fad2b12 429 (print-length nil)
a113b3ca 430 (print-level nil)
1fad2b12
SM
431 (print-readably t) ; This does something in Lucid Emacs.
432 (float-output-format nil)
433 (visited (get-file-buffer file))
438d6bb6 434 (otherbuf nil)
1fad2b12 435 (absfile (expand-file-name file))
1fad2b12 436 ;; nil until we found a cookie.
f8ea0098 437 output-start ostart)
1fad2b12
SM
438 (with-current-buffer (or visited
439 ;; It is faster to avoid visiting the file.
440 (autoload-find-file file))
441 ;; Obey the no-update-autoloads file local variable.
442 (unless no-update-autoloads
443 (message "Generating autoloads for %s..." file)
15120dec
CY
444 (setq load-name
445 (if (stringp generated-autoload-load-name)
446 generated-autoload-load-name
f8ea0098
SM
447 (autoload-file-load-name absfile)))
448 (when (and outfile
283430a1
EZ
449 (not
450 (if (memq system-type '(ms-dos windows-nt))
451 (equal (downcase outfile)
452 (downcase (autoload-generated-file)))
453 (equal outfile (autoload-generated-file)))))
f8ea0098 454 (setq otherbuf t))
1fad2b12
SM
455 (save-excursion
456 (save-restriction
457 (widen)
458 (goto-char (point-min))
459 (while (not (eobp))
460 (skip-chars-forward " \t\n\f")
461 (cond
462 ((looking-at (regexp-quote generate-autoload-cookie))
463 ;; If not done yet, figure out where to insert this text.
464 (unless output-start
f8ea0098
SM
465 (let ((outbuf
466 (or (if otherbuf
467 ;; A file-local setting of
468 ;; autoload-generated-file says we
469 ;; should ignore OUTBUF.
470 nil
471 outbuf)
472 (autoload-find-destination absfile load-name)
473 ;; The file has autoload cookies, but they're
474 ;; already up-to-date. If OUTFILE is nil, the
475 ;; entries are in the expected OUTBUF,
476 ;; otherwise they're elsewhere.
477 (throw 'done otherbuf))))
478 (with-current-buffer outbuf
479 (setq output-start (point-marker)
480 ostart (point)))))
1fad2b12
SM
481 (search-forward generate-autoload-cookie)
482 (skip-chars-forward " \t")
483 (if (eolp)
484 (condition-case err
485 ;; Read the next form and make an autoload.
486 (let* ((form (prog1 (read (current-buffer))
487 (or (bolp) (forward-line 1))))
488 (autoload (make-autoload form load-name)))
489 (if autoload
490 (push (nth 1 form) autoloads-done)
491 (setq autoload form))
f8ea0098
SM
492 (let ((autoload-print-form-outbuf
493 (marker-buffer output-start)))
1fad2b12
SM
494 (autoload-print-form autoload)))
495 (error
ba83908c
SM
496 (message "Autoload cookie error in %s:%s %S"
497 file (count-lines (point-min) (point)) err)))
1fad2b12
SM
498
499 ;; Copy the rest of the line to the output.
500 (princ (buffer-substring
501 (progn
502 ;; Back up over whitespace, to preserve it.
503 (skip-chars-backward " \f\t")
504 (if (= (char-after (1+ (point))) ? )
505 ;; Eat one space.
506 (forward-char 1))
507 (point))
508 (progn (forward-line 1) (point)))
f8ea0098 509 (marker-buffer output-start))))
1fad2b12
SM
510 ((looking-at ";")
511 ;; Don't read the comment.
512 (forward-line 1))
513 (t
514 (forward-sexp 1)
515 (forward-line 1))))))
516
517 (when output-start
0b7750a9 518 (let ((secondary-autoloads-file-buf
f04a3be9 519 (if otherbuf (current-buffer))))
f8ea0098 520 (with-current-buffer (marker-buffer output-start)
0b7750a9
SM
521 (save-excursion
522 ;; Insert the section-header line which lists the file name
523 ;; and which functions are in it, etc.
f8ea0098 524 (assert (= ostart output-start))
0b7750a9 525 (goto-char output-start)
f8ea0098
SM
526 (let ((relfile (file-relative-name absfile)))
527 (autoload-insert-section-header
528 (marker-buffer output-start)
529 autoloads-done load-name relfile
530 (if secondary-autoloads-file-buf
531 ;; MD5 checksums are much better because they do not
532 ;; change unless the file changes (so they'll be
533 ;; equal on two different systems and will change
534 ;; less often than time-stamps, thus leading to fewer
535 ;; unneeded changes causing spurious conflicts), but
536 ;; using time-stamps is a very useful optimization,
537 ;; so we use time-stamps for the main autoloads file
538 ;; (loaddefs.el) where we have special ways to
539 ;; circumvent the "random change problem", and MD5
540 ;; checksum in secondary autoload files where we do
541 ;; not need the time-stamp optimization because it is
542 ;; already provided by the primary autoloads file.
543 (md5 secondary-autoloads-file-buf
544 ;; We'd really want to just use
545 ;; `emacs-internal' instead.
546 nil nil 'emacs-mule-unix)
547 (nth 5 (file-attributes relfile))))
548 (insert ";;; Generated autoloads from " relfile "\n")))
0b7750a9 549 (insert generate-autoload-section-trailer))))
1fad2b12
SM
550 (message "Generating autoloads for %s...done" file))
551 (or visited
552 ;; We created this buffer, so we should kill it.
1c67aeaa 553 (kill-buffer (current-buffer))))
f8ea0098
SM
554 (or (not output-start)
555 ;; If the entries were added to some other buffer, then the file
556 ;; doesn't add entries to OUTFILE.
557 otherbuf))))
e2b6138f 558\f
e66466a6
SM
559(defun autoload-save-buffers ()
560 (while autoload-modified-buffers
561 (with-current-buffer (pop autoload-modified-buffers)
2d8a57ef
GM
562 (let ((version-control 'never))
563 (save-buffer)))))
e66466a6 564
0231f2dc 565;;;###autoload
9ed7c8cb
CY
566(defun update-file-autoloads (file &optional save-after outfile)
567 "Update the autoloads for FILE.
568If prefix arg SAVE-AFTER is non-nil, save the buffer too.
569
570If FILE binds `generated-autoload-file' as a file-local variable,
571autoloads are written into that file. Otherwise, the autoloads
572file is determined by OUTFILE. If called interactively, prompt
573for OUTFILE; if called from Lisp with OUTFILE nil, use the
574existing value of `generated-autoload-file'.
f7ed02ac
RS
575
576Return FILE if there was no autoload cookie in it, else nil."
9ed7c8cb
CY
577 (interactive (list (read-file-name "Update autoloads for file: ")
578 current-prefix-arg
579 (read-file-name "Write autoload definitions to file: ")))
580 (let* ((generated-autoload-file (or outfile generated-autoload-file))
581 (autoload-modified-buffers nil)
1fad2b12
SM
582 (no-autoloads (autoload-generate-file-autoloads file)))
583 (if autoload-modified-buffers
986c5ad5 584 (if save-after (autoload-save-buffers))
32226619 585 (if (called-interactively-p 'interactive)
986c5ad5 586 (message "Autoload section for %s is up to date." file)))
e66466a6 587 (if no-autoloads file)))
57536a83 588
f8ea0098 589(defun autoload-find-destination (file load-name)
57536a83
SM
590 "Find the destination point of the current buffer's autoloads.
591FILE is the file name of the current buffer.
592Returns a buffer whose point is placed at the requested location.
1fad2b12 593Returns nil if the file's autoloads are uptodate, otherwise
0b7750a9 594removes any prior now out-of-date autoload entries."
1fad2b12 595 (catch 'up-to-date
f8ea0098 596 (let* ((buf (current-buffer))
0b7750a9
SM
597 (existing-buffer (if buffer-file-name buf))
598 (found nil))
9ed7c8cb 599 (with-current-buffer (autoload-find-generated-file)
1fad2b12
SM
600 ;; This is to make generated-autoload-file have Unix EOLs, so
601 ;; that it is portable to all platforms.
4c0eb0d3
GM
602 (or (eq 0 (coding-system-eol-type buffer-file-coding-system))
603 (set-buffer-file-coding-system 'unix))
1fad2b12 604 (or (> (buffer-size) 0)
f8ea0098 605 (error "Autoloads file %s lacks boilerplate" buffer-file-name))
1fad2b12
SM
606 (or (file-writable-p buffer-file-name)
607 (error "Autoloads file %s is not writable" buffer-file-name))
608 (widen)
609 (goto-char (point-min))
610 ;; Look for the section for LOAD-NAME.
611 (while (and (not found)
612 (search-forward generate-autoload-section-header nil t))
613 (let ((form (autoload-read-section-header)))
614 (cond ((string= (nth 2 form) load-name)
615 ;; We found the section for this file.
616 ;; Check if it is up to date.
617 (let ((begin (match-beginning 0))
618 (last-time (nth 4 form))
619 (file-time (nth 5 (file-attributes file))))
620 (if (and (or (null existing-buffer)
621 (not (buffer-modified-p existing-buffer)))
0b7750a9
SM
622 (or
623 ;; last-time is the time-stamp (specifying
624 ;; the last time we looked at the file) and
625 ;; the file hasn't been changed since.
626 (and (listp last-time) (= (length last-time) 2)
627 (not (time-less-p last-time file-time)))
628 ;; last-time is an MD5 checksum instead.
629 (and (stringp last-time)
630 (equal last-time
631 (md5 buf nil nil 'emacs-mule)))))
1fad2b12
SM
632 (throw 'up-to-date nil)
633 (autoload-remove-section begin)
634 (setq found t))))
635 ((string< load-name (nth 2 form))
636 ;; We've come to a section alphabetically later than
637 ;; LOAD-NAME. We assume the file is in order and so
638 ;; there must be no section for LOAD-NAME. We will
639 ;; insert one before the section here.
640 (goto-char (match-beginning 0))
641 (setq found t)))))
642 (or found
643 (progn
644 ;; No later sections in the file. Put before the last page.
645 (goto-char (point-max))
646 (search-backward "\f" nil t)))
647 (unless (memq (current-buffer) autoload-modified-buffers)
648 (push (current-buffer) autoload-modified-buffers))
649 (current-buffer)))))
a273d3e0 650
a273d3e0
GM
651(defun autoload-remove-section (begin)
652 (goto-char begin)
653 (search-forward generate-autoload-section-trailer)
654 (delete-region begin (point)))
0231f2dc
JB
655
656;;;###autoload
56eebc29 657(defun update-directory-autoloads (&rest dirs)
9ed7c8cb
CY
658 "Update autoload definitions for Lisp files in the directories DIRS.
659In an interactive call, you must give one argument, the name of a
660single directory. In a call from Lisp, you can supply multiple
56eebc29
RS
661directories as separate arguments, but this usage is discouraged.
662
663The function does NOT recursively descend into subdirectories of the
9ed7c8cb
CY
664directory or directories specified.
665
666In an interactive call, prompt for a default output file for the
667autoload definitions, and temporarily bind the variable
668`generated-autoload-file' to this value. When called from Lisp,
669use the existing value of `generated-autoload-file'. If any Lisp
670file binds `generated-autoload-file' as a file-local variable,
671write its autoloads into the specified file instead."
b59c7256 672 (interactive "DUpdate autoloads from directory: ")
a85e4d58 673 (let* ((files-re (let ((tmp nil))
de10856c 674 (dolist (suf (get-load-suffixes)
a85e4d58
SM
675 (concat "^[^=.].*" (regexp-opt tmp t) "\\'"))
676 (unless (string-match "\\.elc" suf) (push suf tmp)))))
677 (files (apply 'nconc
a273d3e0
GM
678 (mapcar (lambda (dir)
679 (directory-files (expand-file-name dir)
a85e4d58 680 t files-re))
a273d3e0 681 dirs)))
48df920c 682 (done ())
a273d3e0 683 (this-time (current-time))
438d6bb6
SM
684 ;; Files with no autoload cookies or whose autoloads go to other
685 ;; files because of file-local autoload-generated-file settings.
686 (no-autoloads nil)
9ed7c8cb
CY
687 (autoload-modified-buffers nil)
688 (generated-autoload-file
689 (if (called-interactively-p 'interactive)
690 (read-file-name "Write autoload definitions to file: ")
691 generated-autoload-file)))
a273d3e0 692
9ed7c8cb 693 (with-current-buffer (autoload-find-generated-file)
e2b6138f 694 (save-excursion
a273d3e0 695 ;; Canonicalize file names and remove the autoload file itself.
1fad2b12
SM
696 (setq files (delete (file-relative-name buffer-file-name)
697 (mapcar 'file-relative-name files)))
a273d3e0 698
b59c7256
RM
699 (goto-char (point-min))
700 (while (search-forward generate-autoload-section-header nil t)
2336b6a9 701 (let* ((form (autoload-read-section-header))
b59c7256 702 (file (nth 3 form)))
a273d3e0
GM
703 (cond ((and (consp file) (stringp (car file)))
704 ;; This is a list of files that have no autoload cookies.
705 ;; There shouldn't be more than one such entry.
706 ;; Remove the obsolete section.
707 (autoload-remove-section (match-beginning 0))
708 (let ((last-time (nth 4 form)))
709 (dolist (file file)
710 (let ((file-time (nth 5 (file-attributes file))))
711 (when (and file-time
66dc9a0f 712 (not (time-less-p last-time file-time)))
a273d3e0
GM
713 ;; file unchanged
714 (push file no-autoloads)
715 (setq files (delete file files)))))))
716 ((not (stringp file)))
48df920c
SM
717 ((or (not (file-exists-p file))
718 ;; Remove duplicates as well, just in case.
1c67aeaa
SM
719 (member file done)
720 ;; If the file is actually excluded.
721 (member (expand-file-name file) autoload-excludes))
48df920c 722 ;; Remove the obsolete section.
a273d3e0 723 (autoload-remove-section (match-beginning 0)))
0b7750a9
SM
724 ((not (time-less-p (nth 4 form)
725 (nth 5 (file-attributes file))))
a273d3e0
GM
726 ;; File hasn't changed.
727 nil)
b59c7256 728 (t
438d6bb6
SM
729 (autoload-remove-section (match-beginning 0))
730 (if (autoload-generate-file-autoloads
f8ea0098 731 ;; Passing `current-buffer' makes it insert at point.
438d6bb6
SM
732 file (current-buffer) buffer-file-name)
733 (push file no-autoloads))))
48df920c 734 (push file done)
b59c7256 735 (setq files (delete file files)))))
a273d3e0 736 ;; Elements remaining in FILES have no existing autoload sections yet.
438d6bb6 737 (dolist (file files)
1c67aeaa
SM
738 (cond
739 ((member (expand-file-name file) autoload-excludes) nil)
f8ea0098
SM
740 ;; Passing nil as second argument forces
741 ;; autoload-generate-file-autoloads to look for the right
742 ;; spot where to insert each autoloads section.
1c67aeaa
SM
743 ((autoload-generate-file-autoloads file nil buffer-file-name)
744 (push file no-autoloads))))
438d6bb6 745
a273d3e0 746 (when no-autoloads
000d9923
MR
747 ;; Sort them for better readability.
748 (setq no-autoloads (sort no-autoloads 'string<))
a273d3e0
GM
749 ;; Add the `no-autoloads' section.
750 (goto-char (point-max))
751 (search-backward "\f" nil t)
752 (autoload-insert-section-header
753 (current-buffer) nil nil no-autoloads this-time)
754 (insert generate-autoload-section-trailer))
755
2d8a57ef
GM
756 (let ((version-control 'never))
757 (save-buffer))
438d6bb6
SM
758 ;; In case autoload entries were added to other files because of
759 ;; file-local autoload-generated-file settings.
760 (autoload-save-buffers))))
0231f2dc 761
1e0888f5
LH
762(define-obsolete-function-alias 'update-autoloads-from-directories
763 'update-directory-autoloads "22.1")
764
f8641890
GM
765(defvar autoload-make-program (or (getenv "MAKE") "make")
766 "Name of the make program in use during the Emacs build process.")
767
0231f2dc
JB
768;;;###autoload
769(defun batch-update-autoloads ()
b59c7256 770 "Update loaddefs.el autoloads in batch mode.
9ed7c8cb
CY
771Calls `update-directory-autoloads' on the command line arguments.
772Definitions are written to `generated-autoload-file' (which
773should be non-nil)."
5152da64 774 ;; For use during the Emacs build process only.
4a720484
GM
775 ;; Exclude those files that are preloaded on ALL platforms.
776 ;; These are the ones in loadup.el where "(load" is at the start
777 ;; of the line (crude, but it works).
5152da64 778 (unless autoload-excludes
4a720484
GM
779 (let ((default-directory (file-name-directory generated-autoload-file))
780 file)
781 (when (file-readable-p "loadup.el")
782 (with-temp-buffer
783 (insert-file-contents "loadup.el")
784 (while (re-search-forward "^(load \"\\([^\"]+\\)\"" nil t)
785 (setq file (match-string 1))
786 (or (string-match "\\.el\\'" file)
787 (setq file (format "%s.el" file)))
788 (or (string-match "\\`site-" file)
789 (push (expand-file-name file) autoload-excludes)))))))
3a4336e6
MB
790 (let ((args command-line-args-left))
791 (setq command-line-args-left nil)
792 (apply 'update-directory-autoloads args)))
0231f2dc
JB
793
794(provide 'autoload)
ffd56f97 795
c0274f38 796;;; autoload.el ends here