More warning fixes from Nelson
[sxemacs] / lisp / autoload.el
1 ;;; autoload.el --- maintain autoloads in auto-autoloads files.
2
3 ;; Copyright (C) 1991-1994, 1997, 2003 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
5 ;; Copyright (C) 1996, 2000, 2002, 2003, 2004 Ben Wing.
6
7 ;; Original Author: Roland McGrath <roland@gnu.ai.mit.edu>
8 ;; Heavily Modified: XEmacs Maintainers
9 ;; Keywords: maint
10
11 ;; This file is part of SXEmacs.
12
13 ;; SXEmacs is free software: you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation, either version 3 of the License, or
16 ;; (at your option) any later version.
17
18 ;; SXEmacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
26 ;;; Synched up with: FSF 21.2 by Ben Wing.
27 ;;; Note that update-file-autoloads is seriously modified and not really
28 ;;; syncable.
29
30 ;;; Commentary:
31
32 ;; This code keeps auto-autoloads.el files up to date.  It interprets
33 ;; magic cookies (of the form ";;;###autoload" in Lisp source files
34 ;; and "/* ###autoload */" in C source files) in various useful ways.
35 ;; It is also used to maintain custom-defines.el files, since most of
36 ;; the logic for computing them is the same as for auto-autoloads.el.
37
38 ;; Usage
39 ;; =====
40
41 ;; Recommended usage for this library, as implemented in the core
42 ;; build process, is
43
44 ;; sxemacs -no-packages -batch \
45 ;;        -l autoload -f batch-update-directory-autoloads PREFIX DIRECTORY
46
47 ;; which causes XEmacs to update the file named by PATH from the .el
48 ;; files in DIRECTORY (but not recursing into subdirectories) and (if
49 ;; the autoload file is not already protected with a feature test) add
50 ;; a check and provide for 'PREFIX-autoloads.  Currently there is no
51 ;; sanity check for the provided feature; it is recommended that you
52 ;; nuke any existing auto-autoloads.el before running the command.
53
54 ;; There is not yet a recommended API for updating multiple directories
55 ;; into a single auto-autoloads file.  Using the recipe above for each
56 ;; DIRECTORY with the same PATH should work but has not been tested.
57 ;; There is no API for recursing into subdirectories.  There probably
58 ;; won't be; given the wide variety of ways that existing Lisp packages
59 ;; arrange their files, and the fact that source packages and installed
60 ;; packages have a somewhat different directory structure, this seems far
61 ;; too risky.  Use a script or a Lisp library with an explicit list of
62 ;; PATHs; see update-elc.el for how to do this without recursive invocation
63 ;; of XEmacs).
64
65 ;; The probable next step is to fix up the packages to use the
66 ;; `batch-update-directory-autoloads' API.  However, for backward
67 ;; compatibility with XEmacs 21.4 and 21.1, this can't be done quickly.
68
69 ;; For backward compatibility the API used in the packages/XEmacs.rules:
70
71 ;; sxemacs -vanilla -batch -eval "$(AUTOLOAD_PACKAGE_NAME)" \
72 ;;        -l autoload -f batch-update-autoloads $(AUTOLOAD_PATH)
73
74 ;; is supported, and the implementation is unchanged.  However,
75 ;; revision of the API (in a backward compatible way) and the
76 ;; implementation are planned, and until those stabilize it is too
77 ;; risky to use this version of XEmacs for package releases.
78
79 ;; Implementation:
80 ;; ===============
81
82 ;; #### This section should be moved to the Internals manual, or
83 ;; (maybe) the Lispref, and integrated with the information above.
84 ;; Don't believe anything written here; the code is still a mess, and
85 ;; this is a lot of guesswork.
86
87 ;; Autoloads are used in a number of contexts, including core Lisp,
88 ;; packaged Lisp, and ELLs (dynamically loadable compiled objects
89 ;; providing Lisp functionality).  There two general strategies for
90 ;; collecting autoloads.  The first is to put autoloads for a package
91 ;; in a package-specific auto-autoloads file.  This is easy to
92 ;; implement, and allows packages to be distributed with prebuilt
93 ;; auto-autoloads files.  The second is to collect all the autoloads
94 ;; in a single global auto-autoloads file.  This is alleged to speed
95 ;; up initialization significantly, but requires care to ensure that
96 ;; auto-autoloads files remain synchronized with the libraries.
97
98 ;; The traditional logic for determining where to put autoload
99 ;; definitions is complex and is now deprecated.  The special variable
100 ;; `generated-autoload-file' is used to hold the path to the file, and
101 ;; is initialized to the traditional (well, it's a new tradition with
102 ;; XEmacs 20) $blddir/lisp/auto-autoloads.el.  However, this variable
103 ;; may be bound by calling code, or may be generated at collect time
104 ;; and I'm not even sure the initialized value was ever used any more.
105
106 ;; Because there may be multiple auto-autoloads files in use (in XEmacs
107 ;; 21.x with a full complement of packages there are dozens), and they may
108 ;; contain initializations that would be dangerous to reexecute, each is
109 ;; protected by a feature test.  By convention, the feature symbol is of
110 ;; the form "NAME-autoloads".  For packages, the special variable
111 ;; `autoload-package-name' is used to determine NAME.  In the core,
112 ;; autoloads are defined in the modules (all of which are collected in a
113 ;; single auto-autoloads file), using NAME=modules, in the lisp directory
114 ;; using NAME=lisp, and in the lisp/mule directory, using NAME=mule, for
115 ;; the autoloads feature.  These latter are computed by the autoloads
116 ;; function at collect time.
117
118 ;; ChangeLog:
119
120 ;; See ./ChangeLog.
121
122 ;;; Code:
123
124 ;; Need to load easy-mmode because we expand macro calls to easy-mmode
125 ;; macros in make-autoloads below.
126 (require 'easy-mmode)
127
128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
129 ;; Standard file and directory names
130
131 ;; `autoload-file-name' is defvar'd and initialized in packages.el,
132 ;; which is loaded (and dumped) very early.  If you find it isn't, you
133 ;; know what you're doing.
134
135 (defconst autoload-target-directory "../lisp/"
136   "Standard directory containing autoload declaration file.
137
138 Use `generated-autoload-file' (q.v.) to change its installation location.")
139
140 ;; Dynamic variables for communication among functions
141
142 ;; FSF 21.2:
143 ;; The autoload file is assumed to contain a trailer starting with a FormFeed
144 ;; character.
145
146 (defvar generated-autoload-file
147   (expand-file-name autoload-file-name lisp-directory)
148   "*File `update-file-autoloads' puts autoloads into.
149 A .el file can set this in its local variables section to make its
150 autoloads go somewhere else.
151
152 Note that `batch-update-directory' binds this variable to its own value,
153 generally the file named by `autoload-file-name' in the directory being
154 updated.  XEmacs.rules setq's this variable for package autoloads.")
155
156 (defvar generate-autoload-function
157   #'generate-file-autoloads
158   "Function to generate the autoloads for a file and insert at point.
159 Called with one argument, the file.")
160
161 (define-obsolete-variable-alias 'autoload-package-name
162   'autoload-feature-prefix)
163 (defvar autoload-feature-prefix nil
164   "If non-nil, use this string to prefix the autoload feature name.
165
166 Usually a package name (from AUTOLOAD_PACKAGE_NAME, defined in XEmacs.rules
167 in the top of the package hierarchy), or \"auto\" (reserved for the core Lisp
168 auto-autoloads file).  Highest priority candidate except for an explicit
169 argument to `autoload-make-feature-name' (q.v.).")
170
171 (defvar autoload-feature-suffix "-autoloads"
172   "String added to `autoload-feature-prefix' to create the autoload feature name.")
173
174 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
175 ;; Magic strings in source files
176
177 (defconst generate-autoload-cookie ";;;###autoload"
178   "Magic comment indicating the following form should be autoloaded.
179 Used by `update-file-autoloads'.  This string should be
180 meaningless to Lisp (e.g., a comment).
181
182 This string is used:
183
184 ;;;###autoload
185 \(defun function-to-be-autoloaded () ...)
186
187 If this string appears alone on a line, the following form will be
188 read and an autoload made for it.  If it is followed by the string
189 \"immediate\", then the form on the following line will be copied
190 verbatim.  If there is further text on the line, that text will be
191 copied verbatim to `generated-autoload-file'.")
192
193 (defconst generate-c-autoload-cookie "/* ###autoload"
194   "Magic C comment indicating the following form should be autoloaded.
195 Used by `update-file-autoloads'.  This string should be
196 meaningless to C (e.g., a comment).
197
198 This string is used:
199
200 /* ###autoload */
201 DEFUN (\"function-to-be-autoloaded\", ... )
202
203 If this string appears alone on a line, the following form will be
204 read and an autoload made for it.  If there is further text on the line,
205 that text will be copied verbatim to `generated-autoload-file'.")
206
207 (defconst generate-c-autoload-module "/* ###module"
208   "Magic C comment indicating the module containing autoloaded functions.
209 Since a module can consist of multiple C files, the module name may not be
210 the same as the C source file base name.  In that case, use this comment to
211 indicate the actual name of the module from which to autoload functions.")
212
213 (defconst generate-autoload-section-header "\f\n;;;### "
214   "String inserted before the form identifying
215 the section of autoloads for a file.")
216
217 (defconst generate-autoload-section-trailer "\n;;;***\n"
218   "String which indicates the end of the section of autoloads for a file.")
219
220 (defconst generate-autoload-section-continuation ";;;;;; "
221   "String to add on each continuation of the section header form.")
222
223 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
224 ;; Parsing the source file text.
225 ;; Autoloads in C source differ from those in Lisp source.
226 ; Add operator definitions to autoload-operators.el in the xemacs-base
227 ; package.
228 (ignore-errors (require 'autoload-operators))
229
230 ; As autoload-operators is new, provide stopgap measure for a while.
231 (if (not (boundp 'autoload-make-autoload-operators))
232     (progn
233       (defvar autoload-make-autoload-operators
234         '(defun define-skeleton defmacro define-derived-mode define-generic-mode
235           easy-mmode-define-minor-mode easy-mmode-define-global-mode
236           define-minor-mode defun* defmacro*)
237         "`defun'-like operators that use `autoload' to load the library.")
238
239       (defvar autoload-make-autoload-complex-operators
240         '(easy-mmode-define-minor-mode easy-mmode-define-global-mode
241           define-minor-mode)
242         "`defun'-like operators to macroexpand before using `autoload'.")
243
244       (put 'autoload 'doc-string-elt 3)
245       (put 'defun    'doc-string-elt 3)
246       (put 'defun*   'doc-string-elt 3)
247       (put 'defvar   'doc-string-elt 3)
248       (put 'defcustom 'doc-string-elt 3)
249       (put 'defconst 'doc-string-elt 3)
250       (put 'defmacro 'doc-string-elt 3)
251       (put 'defmacro* 'doc-string-elt 3)
252       (put 'defsubst 'doc-string-elt 3)
253       (put 'define-skeleton 'doc-string-elt 2)
254       (put 'define-derived-mode 'doc-string-elt 4)
255       (put 'easy-mmode-define-minor-mode 'doc-string-elt 2)
256       (put 'define-minor-mode 'doc-string-elt 2)
257       (put 'define-generic-mode 'doc-string-elt 7)
258       ;; defin-global-mode has no explicit docstring.
259       (put 'easy-mmode-define-global-mode 'doc-string-elt 1000)))
260
261 (defun make-autoload (form file)
262   "Turn FORM into an autoload or defvar for source file FILE.
263 Returns nil if FORM is not a special autoload form (i.e. a function definition
264 or macro definition or a defcustom)."
265   (let ((car (car-safe form)) expand)
266     (cond
267      ;; For complex cases, try again on the macro-expansion.
268      ((and (memq car autoload-make-autoload-complex-operators)
269            (setq expand (let ((load-file-name file)) (macroexpand form)))
270            (eq (car expand) 'progn)
271            (memq :autoload-end expand))
272       (let ((end (memq :autoload-end expand)))
273         ;; Cut-off anything after the :autoload-end marker.
274         (setcdr end nil)
275         (cons 'progn
276               (mapcar (lambda (form) (make-autoload form file))
277                       (cdr expand)))))
278
279      ;; For special function-like operators, use the `autoload' function.
280      ((memq car autoload-make-autoload-operators)
281       (let* ((macrop (memq car '(defmacro defmacro*)))
282              (name (nth 1 form))
283              (body (nthcdr (get car 'doc-string-elt) form))
284              (doc (if (stringp (car body)) (pop body))))
285         (if (memq car '(defmacro defmacro* defun defun*))
286             (let ((arglist (nth 2 form))
287                   (placeholder (eval-when-compile (gensym))))
288               (setq doc (concat (or doc "")
289                                 "\n\narguments: "
290                                 (replace-in-string
291                                  (cl-function-arglist placeholder arglist)
292                                  (format "^(%s ?" placeholder)
293                                  "(") "\n"))))
294         ;; `define-generic-mode' quotes the name, so take care of that
295         (list 'autoload (if (listp name) name (list 'quote name)) file doc
296               (or (and (memq car '(define-skeleton define-derived-mode
297                                     define-generic-mode
298                                     easy-mmode-define-global-mode
299                                     easy-mmode-define-minor-mode
300                                     define-minor-mode)) t)
301                   (eq (car-safe (car body)) 'interactive))
302               (if macrop (list 'quote 'macro) nil))))
303
304      ;; Convert defcustom to a simpler (and less space-consuming) defvar,
305      ;; but add some extra stuff if it uses :require.
306      ((eq car 'defcustom)
307       (let ((varname (car-safe (cdr-safe form)))
308             (init (car-safe (cdr-safe (cdr-safe form))))
309             (doc (car-safe (cdr-safe (cdr-safe (cdr-safe form)))))
310             (rest (cdr-safe (cdr-safe (cdr-safe (cdr-safe form))))))
311         (if (not (plist-get rest :require))
312             `(defvar ,varname ,init ,doc)
313           `(progn
314              (defvar ,varname ,init ,doc)
315              (custom-add-to-group ,(plist-get rest :group)
316                                   ',varname 'custom-variable)
317              (custom-add-load ',varname
318                               ,(plist-get rest :require))))))
319
320      ;; nil here indicates that this is not a special autoload form.
321      (t nil))))
322
323 (defun make-c-autoload (module)
324   "Make an autoload list for the DEFUN at point in MODULE.
325 Returns nil if the DEFUN is malformed."
326   (and
327    ;; Match the DEFUN
328    (search-forward "DEFUN" nil t)
329    ;; Match the opening parenthesis
330    (progn
331      (skip-syntax-forward " ")
332      (eq (char-after) ?\())
333    ;; Match the opening quote of the Lisp function name
334    (progn
335      (forward-char)
336      (skip-syntax-forward " ")
337      (eq (char-after) ?\"))
338    ;; Extract the Lisp function name, interactive indicator, and docstring
339    (let* ((func-name (let ((begin (progn (forward-char) (point))))
340                        (search-forward "\"" nil t)
341                        (backward-char)
342                        (intern (buffer-substring begin (point)))))
343           (interact (progn
344                       (search-forward "," nil t 4)
345                       (skip-syntax-forward " ")
346                       (not (eq (char-after) ?0))))
347           (begin (progn
348                    (search-forward "/*" nil t)
349                    (forward-line 1)
350                    (point))))
351      (search-forward "*/" nil t)
352      (goto-char (match-beginning 0))
353      (skip-chars-backward " \t\n\f")
354      (list 'autoload (list 'quote func-name) module
355            (buffer-substring begin (point)) interact nil))))
356
357 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
358 ;; Generating autoloads for a single file
359
360 ;;;###autoload
361 (defun generate-file-autoloads (file)
362   "Insert at point an autoload section for FILE.
363 autoloads are generated for defuns and defmacros in FILE
364 marked by `generate-autoload-cookie' (which see).
365 If FILE is being visited in a buffer, the contents of the buffer
366 are used."
367   (interactive "fGenerate autoloads for file: ")
368   (cond ((string-match "\\.el$" file)
369          (generate-autoload-type-section
370           file
371           (replace-in-string (file-name-nondirectory file) "\\.elc?$" "")
372           nil #'generate-lisp-file-autoloads-1))
373         ;; #### jj, are C++ modules possible?
374         ((string-match "\\.c$" file)
375          (generate-autoload-type-section
376           file
377           (replace-in-string (file-name-nondirectory file) "\\.c$" "")
378           t #'generate-c-file-autoloads-1))
379         (t
380          (error 'wrong-type-argument file "not a C or Elisp source file"))))
381
382 (defun* generate-autoload-type-section (file load-name literal fun-to-call)
383   "Insert at point an autoload-type section for FILE.
384 LOAD-NAME is the non-directory portion of the name, with the final .el, .elc
385 or .c section removed.  If LITERAL, open the file literally, without decoding.
386 Calls FUN-TO-CALL to compute the autoloads, with the loaded file in the
387 current buffer, passing it OUTBUF (where to write the autoloads), LOAD-NAME,
388 and TRIM-NAME (result of calling `autoload-trim-file-name' on FILE)."
389   (let ((outbuf (current-buffer))
390         (trim-name (autoload-trim-file-name file))
391         (autoloads-done '())
392         (print-length nil)
393         (print-readably t) ; XEmacs
394         (float-output-format nil)
395         (visited (get-file-buffer file))
396         suppress-form
397         ;; (done-any nil)
398         output-end)
399
400     ;; If the autoload section we create here uses an absolute
401     ;; pathname for FILE in its header, and then Emacs is installed
402     ;; under a different path on another system,
403     ;; `update-autoloads-here' won't be able to find the files to be
404     ;; autoloaded.  So, if FILE is in the same directory or a
405     ;; subdirectory of the current buffer's directory, we'll make it
406     ;; relative to the current buffer's directory.
407     (setq file (expand-file-name file))
408     ;; #### FSF 21.2.  Do we want this?
409 ;     (let* ((source-truename (file-truename file))
410 ;          (dir-truename (file-name-as-directory
411 ;                         (file-truename default-directory)))
412 ;          (len (length dir-truename)))
413 ;       (if (and (< len (length source-truename))
414 ;              (string= dir-truename (substring source-truename 0 len)))
415 ;         (setq file (substring source-truename len))))
416
417     ;; Check for suppression form (XEmacs)
418     (let* ((dir (file-name-directory file))
419            (_pkg (expand-file-name "_pkg.el" dir))
420            (pkg-vis (get-file-buffer _pkg))
421            pkg-buf)
422       (save-excursion
423         (when (file-readable-p _pkg)
424           (unwind-protect
425               (progn
426                 (let ((find-file-hooks nil)
427                       (enable-local-variables nil))
428                   (set-buffer (or pkg-vis (find-file-noselect _pkg)))
429                   (set-syntax-table emacs-lisp-mode-syntax-table))
430                 (save-excursion
431                   (save-restriction
432                     (widen)
433                     (goto-char (point-min))
434                     (block nil
435                       (while (search-forward "(package-suppress" nil t)
436                         ;; skip over package-name
437                         (forward-sexp 1)
438                         (let ((supfile (read (current-buffer))))
439                           (when (equal supfile load-name)
440                             (setq suppress-form (eval (read (current-buffer))))
441                             (return))))))))
442             (unless pkg-vis
443               ;; We created this buffer, so we should kill it.
444               (if pkg-buf (kill-buffer pkg-buf)))))))
445
446     (save-excursion
447       (unwind-protect
448           (progn
449             (let (;(find-file-hooks nil)
450                   ;(enable-local-variables nil)
451                   )
452               (set-buffer (or visited (find-file-noselect file literal literal
453                                                           )))
454               ;; This doesn't look right for C files, but it is.  The only
455               ;; place we need the syntax table is when snarfing the Lisp
456               ;; function name.
457               (set-syntax-table emacs-lisp-mode-syntax-table))
458 ;           (if visited
459 ;               (set-buffer visited)
460 ;             ;; It is faster to avoid visiting the file.
461 ;             (set-buffer (get-buffer-create " *generate-autoload-file*"))
462 ;             (kill-all-local-variables)
463 ;             (erase-buffer)
464 ;             (setq buffer-undo-list t
465 ;                   buffer-read-only nil)
466 ;             ;; This doesn't look right for C files, but it is.  The only
467 ;             ;; place we need the syntax table is when snarfing the Lisp
468 ;             ;; function name.
469 ;             (emacs-lisp-mode)
470 ;             (if literal
471 ;                 (insert-file-contents-literally file nil)
472 ;               (insert-file-contents file nil)))
473             (unless (setq autoloads-done
474                           (funcall fun-to-call outbuf load-name trim-name))
475               (return-from generate-autoload-type-section))
476             )
477         (unless visited
478           ;; We created this buffer, so we should kill it.
479           (kill-buffer (current-buffer)))
480         (set-buffer outbuf)
481         (setq output-end (point-marker))))
482     (if t ;; done-any
483         ;; XEmacs -- always do this so that we cache the information
484         ;; that we've processed the file already.
485         (progn
486           ;; Insert the section-header line
487           ;; which lists the file name and which functions are in it, etc.
488           (insert generate-autoload-section-header)
489           (prin1 (list 'autoloads autoloads-done load-name trim-name
490                        ;; In FSF 21.2.  Also in FSF 19.30.  Presumably
491                        ;; deleted from XEmacs.
492                        ;; (nth 5 (file-attributes file))
493                        )
494                  outbuf)
495           (terpri outbuf)
496           ;; #### Alas, we will have to think about this.  Adding this means
497           ;; that, once we have created or maintained an auto-autoloads file,
498           ;; we alone and our successors can update the file.  The file itself
499           ;; will work fine in older XEmacsen, but they won't be able to
500           ;; update autoloads -- hence, to build.
501 ;         ;; Break that line at spaces, to avoid very long lines.
502 ;         ;; Make each sub-line into a comment.
503 ;         (with-current-buffer outbuf
504 ;           (save-excursion
505 ;             (forward-line -1)
506 ;             (while (not (eolp))
507 ;               (move-to-column 64)
508 ;               (skip-chars-forward "^ \n")
509 ;               (or (eolp)
510 ;                   (insert "\n" generate-autoload-section-continuation)))))
511           ;; XEmacs: This was commented out before.  #### Correct?
512 ;         (insert ";;; Generated autoloads from "
513 ;                 (autoload-trim-file-name file) "\n")
514           ;; XEmacs -- handle suppression
515           (when suppress-form
516             (insert "\n;;; Suppress form from _pkg.el\n")
517             (insert "(unless " (prin1-to-string suppress-form) "\n\n"))
518           (goto-char output-end)
519           ;; XEmacs -- handle suppression
520           (when suppress-form
521             (insert "\n) ;; unless (suppressed)\n"))
522           (insert generate-autoload-section-trailer)))
523     ))
524
525
526 (defun process-one-lisp-autoload (autoloads-done outbuf load-name)
527   "Process a single autoload at point and write to OUTBUF.
528 Point should be just after a magic cookie string (e.g. ;;;###autoload).
529 Updates AUTOLOADS-DONE and returns the new value."
530   (skip-chars-forward " \t")
531   ;; (setq done-any t)
532   (if (eolp)
533       ;; Read the next form and make an autoload.
534       (let* ((form (prog1 (read (current-buffer))
535                      (or (bolp) (forward-line 1))))
536              (autoload (make-autoload form load-name)))
537         (if autoload
538             (setq autoloads-done (cons (nth 1 form)
539                                        autoloads-done))
540           (setq autoload form))
541         (autoload-print-form autoload outbuf ""))
542     ;; Copy the rest of the line to the output.
543     (cond ((looking-at "immediate\\s *$") ; XEmacs
544            ;; This is here so that you can automatically
545            ;; have small hook functions copied to
546            ;; auto-autoloads.el so that it's not necessary
547            ;; to load a whole file just to get a two-line
548            ;; do-nothing find-file-hook... --Stig
549            (forward-line 1)
550            (let ((begin (point)))
551              (forward-sexp)
552              (forward-line 1)
553              (princ (buffer-substring begin (point)) outbuf))
554            (setq autoloads-done (cons '<immediate> autoloads-done)))
555           (t
556            (princ (buffer-substring
557                    (progn
558                      ;; Back up over whitespace, to preserve it.
559                      (skip-chars-backward " \f\t")
560                      (if (= (char-after (1+ (point))) ? )
561                          ;; Eat one space.
562                          (forward-char 1))
563                      (point))
564                    (progn (forward-line 1) (point)))
565                   outbuf))))
566   autoloads-done)
567
568 (defun* generate-lisp-file-autoloads-1 (outbuf load-name trim-name)
569   "Insert at point in OUTBUF an autoload section for an Elisp file.
570 The file is assumed to be already loaded and in the current buffer.
571 autoloads are generated for defuns and defmacros marked by
572 `generate-autoload-cookie' (which see)."
573   (let ((autoloads-done '())
574         )
575     (save-excursion
576       (save-restriction
577         (widen)
578         (goto-char (point-min))
579         (unless (search-forward generate-autoload-cookie nil t)
580           (message "No autoloads found in %s" trim-name)
581           (return-from generate-lisp-file-autoloads-1 nil))
582
583         (message "Generating autoloads for %s..." trim-name)
584         (goto-char (point-min))
585         (while (not (eobp))
586           (skip-chars-forward " \t\n\f")
587           (cond
588            ((looking-at (regexp-quote generate-autoload-cookie))
589             (search-forward generate-autoload-cookie)
590             (setq autoloads-done
591                   (process-one-lisp-autoload autoloads-done outbuf load-name)))
592            ((looking-at ";")
593             ;; Don't read the comment.
594             (forward-line 1))
595            (t
596             (forward-sexp 1)
597             (forward-line 1)))
598           )))
599     (or noninteractive ; XEmacs: only need one line in -batch mode.
600         (message "Generating autoloads for %s...done" trim-name))
601     autoloads-done))
602
603 (defun* generate-c-file-autoloads-1 (outbuf load-name trim-name
604                                      &optional funlist)
605   "Insert at point an autoload section for the C file FILE.
606 autoloads are generated for defuns and defmacros in FILE
607 marked by `generate-c-autoload-cookie' (which see).
608 If FILE is being visited in a buffer, the contents of the buffer
609 are used."
610   (let (autoloads-done)
611     (save-excursion
612       (save-restriction
613         (widen)
614         (goto-char (point-min))
615         ;; Is there a module name comment?
616         (when (search-forward generate-c-autoload-module nil t)
617           (skip-chars-forward " \t")
618           (let ((begin (point)))
619             (skip-chars-forward "^ \t\n\f")
620             (setq load-name (buffer-substring begin (point)))))
621         (if funlist
622             (progn
623               (message "Generating autoloads for %s..." trim-name)
624               (dolist (arg funlist)
625                 (goto-char (point-min))
626                 (re-search-forward
627                  (concat "DEFUN (\""
628                          (regexp-quote (symbol-name arg))
629                          "\""))
630                 (goto-char (match-beginning 0))
631                 (let ((autoload (make-c-autoload load-name)))
632                   (when autoload
633                     (push (nth 1 (nth 1 autoload)) autoloads-done)
634                     (autoload-print-form autoload outbuf "")))))
635           (goto-char (point-min))
636           (let ((match
637                  (search-forward generate-c-autoload-cookie nil t)))
638             (unless match
639               (message "No autoloads found in %s" trim-name)
640               (return-from generate-c-file-autoloads-1 nil))
641             (message "Generating autoloads for %s..." trim-name)
642             (while match
643               (forward-line 1)
644               (let ((autoload (make-c-autoload load-name)))
645                 (when autoload
646                   (push (nth 1 (nth 1 autoload)) autoloads-done)
647                   (autoload-print-form autoload outbuf "")))
648               (setq match
649                     (search-forward generate-c-autoload-cookie nil t)))))))
650     (or noninteractive ; XEmacs: only need one line in -batch mode.
651         (message "Generating autoloads for %s...done" trim-name))
652     autoloads-done))
653
654 ;;;###autoload
655 (defun generate-custom-defines (file)
656   "Insert at point a custom-define section for FILE.
657 If FILE is being visited in a buffer, the contents of the buffer
658 are used."
659   (interactive "fGenerate custom defines for file: ")
660   (cond ((string-match "\\.el$" file)
661          (generate-autoload-type-section
662           file
663           (replace-in-string (file-name-nondirectory file) "\\.elc?$" "")
664           nil #'generate-custom-defines-1))
665         ((string-match "\\.c$" file)
666          ;; no way to generate custom-defines for C files (currently?),
667          ;; but cannot signal an error.
668          nil)
669         (t
670          (error 'wrong-type-argument file "not a C or Elisp source file"))))
671
672 (defun* generate-custom-defines-1 (outbuf load-name trim-name)
673   "Insert at point in OUTBUF a custom-define section for an Elisp file.
674 This contains all defcustoms and defgroups in the file.
675 The file is assumed to be already loaded and in the current buffer."
676   (let* ((search-regexp-1 "^(\\(defcustom\\|defgroup\\) ")
677          (search-string-2 ";;;###custom-define")
678          (search-regexp-2 (regexp-quote search-string-2))
679          (autoloads-done '()))
680     (save-excursion
681       (save-restriction
682         (widen)
683         (goto-char (point-min))
684         (unless (or (re-search-forward search-regexp-1 nil t)
685                     (re-search-forward search-regexp-2 nil t))
686           (message "No custom defines found in %s" trim-name)
687           (return-from generate-custom-defines-1 nil))
688         (message "Generating custom defines for %s..." trim-name)
689         (princ "(defconst custom-define-current-source-file " outbuf)
690         (prin1 (file-relative-name (buffer-file-name)
691                                    (symbol-value-in-buffer 'default-directory
692                                                            outbuf)) outbuf)
693         (princ ")\n" outbuf)
694
695         (goto-char (point-min))
696         (while (not (eobp))
697           (skip-chars-forward " \t\n\f")
698           (cond
699            ((looking-at search-regexp-1)
700             ;; Read the next form and copy it to make an autoload.
701             (let* ((form (prog1 (read (current-buffer))
702                            (or (bolp) (forward-line 1))))
703                    (autoload form ;(make-autoload form load-name)
704                      ))
705               (if autoload
706                   (setq autoloads-done (cons (nth 1 form)
707                                              autoloads-done))
708                 (setq autoload form))
709               (autoload-print-form autoload outbuf ""))
710             )
711            ((looking-at search-regexp-2)
712             (search-forward search-string-2)
713             (beep)
714             (setq autoloads-done
715                   (process-one-lisp-autoload autoloads-done outbuf load-name)))
716            ((looking-at ";")
717             ;; Don't read the comment.
718             (forward-line 1))
719            (t
720             (forward-sexp 1)
721             (forward-line 1)))
722           )))
723     (or noninteractive ; XEmacs: only need one line in -batch mode.
724         (message "Generating custom defines for %s...done" trim-name))
725     autoloads-done))
726
727 ;; Assorted utilities for generating autoloads and pieces thereof
728
729 (defun autoload-print-form (form outbuf margin)
730   "Print an autoload form, handling special characters.
731 In particular, print docstrings with escapes inserted before left parentheses
732 at the beginning of lines and ^L characters."
733   (cond
734    ;; If the form is a sequence, recurse.
735    ((eq (car form) 'progn)
736     (mapcar #'(lambda (x) (autoload-print-form x outbuf margin))
737             (cdr form)))
738    ;; Symbols at the toplevel are meaningless.
739    ((symbolp form) nil)
740    (t
741     (let ((doc-string-elt (get (car-safe form) 'doc-string-elt)))
742       (if (and doc-string-elt (stringp (nth doc-string-elt form)))
743           ;; We need to hack the printing because the doc-string must be
744           ;; printed specially for make-docfile (sigh).
745           (let* ((p (nthcdr (1- doc-string-elt) form))
746                  (elt (cdr p))
747                  (start-string (format "\n%s(" margin)))
748             (setcdr p nil)
749             (princ start-string outbuf)
750             ;; XEmacs change: don't let ^^L's get into
751             ;; the file or sorting is hard.
752             (let ((print-escape-newlines t)
753                   ;;#### FSF 21.2 (print-escape-nonascii t)
754                   (p (point outbuf))
755                   p2)
756               (mapcar #'(lambda (elt)
757                           (prin1 elt outbuf)
758                           (princ " " outbuf))
759                       form)
760               (with-current-buffer outbuf
761                 (setq p2 (point-marker))
762                 (goto-char p)
763                 (save-match-data
764                   (while (search-forward "\^L" p2 t)
765                     (delete-char -1)
766                     (insert "\\^L")))
767                 (goto-char p2)))
768             (princ "\"\\\n" outbuf)
769             (let ((begin (point outbuf)))
770               (princ (substring (prin1-to-string (car elt)) 1) outbuf)
771               ;; Insert a backslash before each ( that appears at the beginning
772               ;; of a line in the doc string.
773               (with-current-buffer outbuf
774                 (save-excursion
775                   (while (search-backward start-string begin t)
776                     (forward-char 1)
777                     (insert "\\"))))
778               (if (null (cdr elt))
779                   (princ ")" outbuf)
780                 (princ " " outbuf)
781                 (princ (substring (prin1-to-string (cdr elt)) 1) outbuf))
782               (terpri outbuf)
783               (princ margin outbuf)))
784         ;; XEmacs change: another ^L hack
785         (let ((p (point outbuf))
786               (print-escape-newlines t)
787               ;;#### FSF 21.2 (print-escape-nonascii t)
788               p2)
789           (print form outbuf)
790           (with-current-buffer outbuf
791             (setq p2 (point-marker))
792             (goto-char p)
793             (save-match-data
794               (while (search-forward "\^L" p2 t)
795                 (delete-char -1)
796                 (insert "\\^L")))
797             (goto-char p2))))))))
798
799 ;;; Forms which have doc-strings which should be printed specially.
800 ;;; A doc-string-elt property of ELT says that (nth ELT FORM) is
801 ;;; the doc-string in FORM.
802 ;;;
803 ;;; There used to be the following note here:
804 ;;; ;;; Note: defconst and defvar should NOT be marked in this way.
805 ;;; ;;; We don't want to produce defconsts and defvars that
806 ;;; ;;; make-docfile can grok, because then it would grok them twice,
807 ;;; ;;; once in foo.el (where they are given with ;;;###autoload) and
808 ;;; ;;; once in loaddefs.el.
809 ;;;
810 ;;; Counter-note: Yes, they should be marked in this way.
811 ;;; make-docfile only processes those files that are loaded into the
812 ;;; dumped Emacs, and those files should never have anything
813 ;;; autoloaded here.  The above-feared problem only occurs with files
814 ;;; which have autoloaded entries *and* are processed by make-docfile;
815 ;;; there should be no such files.
816
817 (put 'autoload 'doc-string-elt 3)
818 (put 'defun    'doc-string-elt 3)
819 (put 'defun*   'doc-string-elt 3)
820 (put 'defvar   'doc-string-elt 3)
821 (put 'defcustom 'doc-string-elt 3)
822 (put 'defconst 'doc-string-elt 3)
823 (put 'defmacro 'doc-string-elt 3)
824 (put 'defmacro* 'doc-string-elt 3)
825 (put 'defsubst 'doc-string-elt 3)
826 (put 'define-skeleton 'doc-string-elt 2)
827 (put 'define-derived-mode 'doc-string-elt 4)
828 (put 'easy-mmode-define-minor-mode 'doc-string-elt 2)
829 (put 'define-minor-mode 'doc-string-elt 2)
830 (put 'define-generic-mode 'doc-string-elt 7)
831 ;; defin-global-mode has no explicit docstring.
832 (put 'easy-mmode-define-global-mode 'doc-string-elt 1000)
833
834 (defun autoload-trim-file-name (file)
835   "Returns relative pathname of FILE including the last directory."
836   (setq file (expand-file-name file))
837   (file-relative-name file (file-name-directory
838                             (directory-file-name
839                              (file-name-directory file)))))
840
841 (defun autoload-read-section-header ()
842   "Read a section header form.
843 Since continuation lines have been marked as comments,
844 we must copy the text of the form and remove those comment
845 markers before we call `read'."
846   (save-match-data
847     (let ((beginning (point))
848           string)
849       (forward-line 1)
850       (while (looking-at generate-autoload-section-continuation)
851         (forward-line 1))
852       (setq string (buffer-substring beginning (point)))
853       (with-current-buffer (get-buffer-create " *autoload*")
854         (erase-buffer)
855         (insert string)
856         (goto-char (point-min))
857         (while (search-forward generate-autoload-section-continuation nil t)
858           (replace-match " "))
859         (goto-char (point-min))
860         (read (current-buffer))))))
861
862 ;;;###autoload
863 (defun update-file-autoloads (file)
864   "Update the autoloads for FILE in `generated-autoload-file'
865 \(which FILE might bind in its local variables).
866 This function is a no-op for an autoloads file (ie, a file whose name is
867 equal to `autoload-file-name')."
868   (interactive "fUpdate autoloads for file: ")
869   (setq file (expand-file-name file))
870   (when (and (file-newer-than-file-p file generated-autoload-file)
871              (not (member (file-name-nondirectory file)
872                           (list autoload-file-name))))
873
874     (let ((load-name (replace-in-string (file-name-nondirectory file)
875                                         "\\.\\(elc?\\|c\\)$"
876                                         ""))
877           (trim-name (autoload-trim-file-name file))
878           section-begin form)
879       (save-excursion
880         ;; FSF has: [[ We want to get a value for generated-autoload-file
881         ;; from the local variables section if it's there. ]] Not
882         ;; applicable in XEmacs, since we always keep the autoloads
883         ;; up-to-date.
884
885         ;; #### FSF 21.2 adds: [[ We must read/write the file without any
886         ;; code conversion, but still decode EOLs. ]] Not clear if we need
887         ;; this. --ben
888         ;; (let ((coding-system-for-read 'raw-text))
889         (let ((find-file-hooks nil))
890           (set-buffer (or (get-file-buffer generated-autoload-file)
891                           (find-file-noselect generated-autoload-file))))
892         ;; FSF 21.2 says:
893
894         ;; [[ This is to make generated-autoload-file have Unix EOLs, so
895         ;; that it is portable to all platforms. ]]
896         ;; (setq buffer-file-coding-system 'raw-text-unix))
897         ;; Not applicable in XEmacs, since we always keep the autoloads
898         ;; up-to-date and recompile when we build.
899
900         ;; FSF 21.2: [not applicable to XEmacs]
901 ;       (or (> (buffer-size) 0)
902 ;           (error "Autoloads file %s does not exist" buffer-file-name))
903 ;       (or (file-writable-p buffer-file-name)
904 ;           (error "Autoloads file %s is not writable" buffer-file-name))
905
906         ;; NOTE: The rest of this function is totally changed from FSF.
907         ;; Hence, not synched.
908
909         ;; Make sure we can scribble in it.
910         (setq buffer-read-only nil)
911         ;; First delete all sections for this file.
912         (goto-char (point-min))
913         (while (search-forward generate-autoload-section-header nil t)
914           (setq section-begin (match-beginning 0))
915           (setq form (autoload-read-section-header))
916           (when (string= (nth 2 form) load-name)
917             (search-forward generate-autoload-section-trailer)
918             (delete-region section-begin (point))))
919
920         ;; Now find insertion point for new section
921         (block find-insertion-point
922           (goto-char (point-min))
923           (while (search-forward generate-autoload-section-header nil t)
924             (setq form (autoload-read-section-header))
925             (when (string< trim-name (nth 3 form))
926               ;; Found alphabetically correct insertion point
927               (goto-char (match-beginning 0))
928               (return-from find-insertion-point))
929             (search-forward generate-autoload-section-trailer))
930           (when (eq (point) (point-min))        ; No existing entries?
931             (goto-char (point-max))))   ; Append.
932
933         ;; Add in new sections for file
934         (funcall generate-autoload-function file))
935
936       (when (interactive-p) (save-buffer)))))
937
938 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
939 ;; Utilities for batch updates
940
941 (defun parse-command-line (cmdl)
942   (let ((newcmdl (dllist))
943         (cmdlpl (make-skiplist))
944         (mm (compile-regexp "^--"))
945         (ign (compile-regexp #r"^-\(?:batch\|nd\|vanilla\)"))
946         (ign2 (compile-regexp "^-[lf]$")))
947     (while (car cmdl)
948       (cond ((string-match mm (car cmdl))
949              (let ((key (intern (car cmdl)))
950                    (val (car (cdr-safe cmdl))))
951                (put-skiplist cmdlpl key val)
952                (setq cmdl (cdr-safe cmdl))))
953             ((string-match ign2 (car cmdl))
954              ;; ignore a pair of parameters
955              (setq cmdl (cdr-safe cmdl)))
956             ((string-match ign (car cmdl))
957              ;; ignore this single parameter
958              )
959             (t
960              (dllist-append newcmdl (car cmdl))))
961       (setq cmdl (cdr-safe cmdl)))
962     (put newcmdl :tweaks cmdlpl)
963     newcmdl))
964
965 ;;;###autoload
966 (defun batch-create-autoloads ()
967   "Update the autoloads for one or more directories.
968
969 #### The API and semantics of this function are subject to change."
970   (unless noninteractive
971     (error "batch-update-directory-autoloads: may be used only with -batch"))
972
973   (let* ((cmds (parse-command-line (cdr-safe command-line-args)))
974          (pl (get cmds :tweaks)))
975
976     (unless (get-skiplist pl '--autoload-dir-name)
977       (put-skiplist pl '--autoload-dir-name
978                     (expand-file-name default-directory)))
979     (unless (get-skiplist pl '--autoload-file-name)
980       (put-skiplist pl '--autoload-file-name
981                     (expand-file-name autoload-file-name
982                                       (get-skiplist pl '--autoload-dir-name))))
983     (unless (get-skiplist pl '--feature-prefix)
984       (put-skiplist pl '--feature-prefix
985                     (file-name-nondirectory
986                      (directory-file-name
987                       (expand-file-name
988                        (get-skiplist pl '--autoload-dir-name))))))
989
990     (create-autoload-files cmds t)))
991
992 (defun create-autoload-files (bunch &optional force)
993   (let* ((pl (get bunch :tweaks))
994          (relative (get-skiplist pl '--relative-to))
995          (al-file (get-skiplist pl '--autoload-file-name))
996          (fprefix (get-skiplist pl '--feature-prefix)))
997     (mapc-inplace
998      #'(lambda (dir)
999          (expand-file-name dir relative))
1000      bunch)
1001     (update-autoload-files (dllist-to-list bunch) fprefix al-file force)))
1002
1003 ;;;###autoload
1004 (defun batch-update-directory-autoloads ()
1005   "Update the autoloads for a directory, using a specified feature prefix.
1006 Must be used only with -batch.  The feature prefix and directory to update
1007 are taken from the first and second elements of `command-line-args-left',
1008 respectively, and they are then removed from `command-line-args-left'.
1009
1010 Runs `update-file-autoloads' on each file in the given directory.  Always
1011 rewrites the autoloads file, even if unchanged.  Makes a feature name by
1012 applying `autoload-make-feature-name' to the specified feature prefix.
1013
1014 #### The API and semantics of this function are subject to change."
1015   (unless noninteractive
1016     (error "batch-update-directory-autoloads: may be used only with -batch"))
1017   (update-autoload-files (list (cadr command-line-args-left))
1018                          (car command-line-args-left) nil t)
1019   (setq command-line-args-left (cddr command-line-args-left)))
1020
1021 ;;;###autoload
1022 (defun batch-update-directory-custom-defines ()
1023   "Update the custom defines for a directory, using a specified feature prefix.
1024 Must be used only with -batch.  The feature prefix and directory to update
1025 are taken from the first and second elements of `command-line-args-left',
1026 respectively, and they are then removed from `command-line-args-left'.
1027
1028 Runs `update-file-autoloads' on each file in the given directory.  Always
1029 rewrites the autoloads file, even if unchanged.  Makes a feature name by
1030 applying `autoload-make-feature-name' to the specified feature prefix.
1031
1032 #### The API and semantics of this function are subject to change."
1033   (unless noninteractive
1034     (error "batch-update-directory-custom-defines: may be used only with -batch"))
1035   (update-custom-define-files (list (cadr command-line-args-left))
1036                               (car command-line-args-left) nil t)
1037   (setq command-line-args-left (cddr command-line-args-left)))
1038
1039 ;;;###autoload
1040 (defun update-autoload-files (files-or-dirs feature-prefix
1041                               &optional into-file force)
1042   "Update all the autoload files associated with FILES-OR-DIRS.
1043 FILES-OR-DIRS is a list of files and/or directories to be processed.
1044
1045 An appropriate autoload file is chosen and a feature constructed for
1046 each element of FILES-OR-DIRS.  Fixup code testing for the autoload file's
1047 feature and to provide the feature is added.
1048
1049 If optional INTO-FILE is non-`nil', it should specify a file into which
1050 the autoloads will be placed.  Otherwise, the autoloads will be placed into
1051 a file named `auto-autoloads.el' in the directory of each element in
1052 FILES-OR-DIRS.
1053
1054 FEATURE-PREFIX should be set to an appropriate prefix which will
1055 be concatenated with \"-autoloads\" to produce the feature name.  Otherwise
1056 the appropriate autoload file for each file or directory (located in that
1057 directory, or in the directory of the specified file) will be updated with
1058 the directory's or file's autoloads and the protective forms will be added,
1059 and the files will be saved.  Use of the default here is unreliable, and
1060 therefore deprecated.
1061
1062 Note that if some of FILES-OR-DIRS are directories, recursion goes only
1063 one level deep.
1064
1065 If FORCE is non-nil, always save out the autoload files even if unchanged."
1066   (or (listp files-or-dirs) (setq files-or-dirs (list files-or-dirs)))
1067   (let ((defdir (directory-file-name default-directory))
1068         ;; value for all-into-one-file
1069         (autoload-feature-name (autoload-make-feature-name feature-prefix))
1070         (enable-local-eval nil) ; Don't query in batch mode.
1071         (autoload-feature-prefix feature-prefix)
1072         ;; protect from change
1073         (generated-autoload-file generated-autoload-file))
1074     (dolist (arg files-or-dirs)
1075       (setq arg (expand-file-name arg defdir))
1076       (cond
1077        ((file-directory-p arg)
1078         (setq generated-autoload-file
1079               (or into-file (expand-file-name autoload-file-name arg)))
1080         (message "Updating autoloads for directory %s..." arg)
1081         (let ((simple-dir (file-name-as-directory
1082                            (file-name-nondirectory
1083                             (directory-file-name arg))))
1084               (enable-local-eval nil))
1085           (save-excursion
1086             (let ((find-file-hooks nil))
1087               (set-buffer (find-file-noselect generated-autoload-file)))
1088             (goto-char (point-min))
1089             (while (search-forward generate-autoload-section-header nil t)
1090               (let* ((begin (match-beginning 0))
1091                      (form (autoload-read-section-header))
1092                      (file (nth 3 form)))
1093                 (when (and (stringp file)
1094                            (string= (file-name-directory file) simple-dir)
1095                            (not (file-exists-p
1096                                  (expand-file-name
1097                                   (file-name-nondirectory file) arg))))
1098                   ;; Remove the obsolete section.
1099                   (search-forward generate-autoload-section-trailer)
1100                   (delete-region begin (point)))))
1101             ;; Update or create autoload sections for existing files.
1102             (mapcar 'update-file-autoloads
1103                     (directory-files arg t "^[^=].*\\.\\(el\\|c\\)$")))))
1104        ((file-exists-p arg)
1105         (setq generated-autoload-file
1106               (or into-file (expand-file-name autoload-file-name
1107                                               (file-name-directory arg))))
1108         (update-file-autoloads arg))
1109        (t (error "No such file or directory: %s" arg)))
1110       (when (not into-file)
1111         (autoload-featurep-protect-autoloads
1112          (autoload-make-feature-name
1113           (or feature-prefix
1114               (file-name-nondirectory (directory-file-name arg)))))
1115         (if force (set-buffer-modified-p
1116                    t (find-file-noselect generated-autoload-file)))))
1117     (when into-file
1118       (autoload-featurep-protect-autoloads autoload-feature-name)
1119       (if force (set-buffer-modified-p
1120                  t (find-file-noselect into-file))))
1121     (save-some-buffers t)
1122     ))
1123
1124 ;;;###autoload
1125 (defun update-custom-define-files (files-or-dirs feature-prefix
1126                                    &optional into-file force)
1127   "Update all the custom-define files associated with FILES-OR-DIRS.
1128 Works just like `update-file-autoloads'."
1129   (let* ((autoload-feature-suffix "-custom-defines")
1130          (autoload-file-name "custom-defines.el")
1131          (generate-autoload-function #'generate-custom-defines))
1132     (update-autoload-files files-or-dirs feature-prefix into-file force)))
1133
1134 (defun autoload-featurep-protect-autoloads (sym)
1135   (save-excursion
1136     (set-buffer (find-file-noselect generated-autoload-file))
1137     (goto-char (point-min))
1138     (cond ((eq (point-min) (point-max)) nil)
1139           ;; if there's some junk in the file but no sections, just
1140           ;; delete everything.  the junk might be stuff inserted by
1141           ;; an older version of this function.
1142           ((not (search-forward generate-autoload-section-header nil t))
1143            (delete-region (point-min) (point-max)))
1144           (t
1145            (goto-char (point-min))
1146            (when (looking-at ";;; DO NOT MODIFY THIS FILE")
1147              (delete-region (point-min)
1148                             (progn
1149                               (search-forward generate-autoload-section-header)
1150                               (match-beginning 0))))
1151            ;; Determine and set the coding system for the file if under Mule.
1152            ;; If there are any extended characters in the input file, use
1153            ;; `escape-quoted' to make sure that both binary and extended
1154            ;; characters are output properly and distinguished properly.
1155            ;; Otherwise, use `raw-text' for maximum portability with non-Mule
1156            ;; Emacsen.
1157            (if (or (featurep '(not mule)) ;; Don't scan if no Mule support
1158                    (progn
1159                      (goto-char (point-min))
1160                      ;; mrb- There must be a better way than skip-chars-forward
1161                      (skip-chars-forward (concat (char-to-string 0) "-"
1162                                                  (char-to-string 255)))
1163                      (eq (point) (point-max))))
1164                (setq buffer-file-coding-system 'raw-text-unix)
1165              (setq buffer-file-coding-system 'escape-quoted))
1166            (goto-char (point-min))
1167            (insert ";;; DO NOT MODIFY THIS FILE")
1168            ;; NOTE: XEmacs prior to 21.5.12 or so had a bug in that it
1169            ;; recognized only one of the two magic-cookie styles (the -*- kind)
1170            ;; in find-file, but both of them in load.  We go ahead and put both
1171            ;; in, just to be safe.
1172            (when (eq buffer-file-coding-system 'escape-quoted)
1173              (insert " -*- coding: escape-quoted; -*-
1174 \(or (featurep 'mule) (error \"Loading this file requires Mule support\"))
1175 ;;;###coding system: escape-quoted"))
1176            (insert "\n(if (featurep '" sym ")")
1177            (insert " (error \"Feature " sym " already loaded\"))\n")
1178            (goto-char (point-max))
1179            (save-excursion
1180              (forward-line -1)
1181              (when (looking-at "(provide")
1182                (delete-region (point) (point-max))))
1183            (unless (bolp) (insert "\n"))
1184            (unless (eq (char-before (1- (point))) ?\^L)
1185              (insert "\^L\n"))
1186            (insert "(provide '" sym ")\n")))))
1187
1188 (defun autoload-make-feature-name (&optional prefix)
1189   "Generate the feature name to protect this auto-autoloads file from PREFIX.
1190
1191 If PREFIX is nil, it defaults to the value of `autoload-feature-prefix' if
1192 that is non-nil.
1193
1194 The feature name must be globally unique for this version of XEmacs,
1195 including packages.
1196
1197 For backward compatibility, if PREFIX and `autoload-feature-prefix' are both
1198 `nil', PREFIX is computed as the last directory component of
1199 `generated-autoload-file'.  This is likely to result in non-uniqueness, so
1200 do not use this feature."
1201   (concat
1202    (cond (prefix)
1203          (autoload-feature-prefix)
1204          ((stringp generated-autoload-file)
1205           (message "Warning: autoload computing feature prefix.
1206 You should specify it as an argument to `autoload-make-feature-name'.")
1207           (file-name-nondirectory
1208            (directory-file-name
1209             (file-name-directory generated-autoload-file))))
1210          (t (error 'invalid-argument
1211                    "Could not compute a feature name")))
1212    autoload-feature-suffix))
1213
1214 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1215 ;; Deprecated entry points
1216
1217 ;; A grep of the core and packages shows use of `batch-update-autoloads'
1218 ;; by XEmacs.rules, pcomplete, eshell, oort-gnus; `batch-update-directory'
1219 ;; by liece.  The other two entry points (`batch-update-one-directory',
1220 ;; `batch-force-update-one-directory') were not used at all.
1221 ;;
1222 ;; All except the first are now history.  liece has been updated.
1223 ;; XEmacs.rules has been updated.  The others will be, eventually.
1224
1225 ;; There don't seem to be very many packages that use the first one (the
1226 ;; "all-into-one-file" variety), and do they actually rely on this
1227 ;; functionality? --ben
1228
1229 ;; but XEmacs.rules does, though maybe it doesn't "rely" on it, and
1230 ;; modules do now, and that relies on it. --sjt
1231
1232 ;;;###autoload
1233 (defun batch-update-autoloads ()
1234   "Update the autoloads for the files or directories on the command line.
1235 Runs `update-file-autoloads' on files and `update-directory-autoloads'
1236 on directories.  Must be used only with -batch, and kills Emacs on completion.
1237 Each file will be processed even if an error occurred previously.
1238 For example, invoke `xemacs -batch -f batch-update-autoloads *.el'.
1239 The directory to which the auto-autoloads.el file must be the first parameter
1240 on the command line."
1241   (unless noninteractive
1242     (error "batch-update-autoloads is to be used only with -batch"))
1243   (update-autoload-files command-line-args-left autoload-feature-prefix
1244                          generated-autoload-file t)
1245   (kill-emacs 0))
1246
1247 ;; Declare obsolescence
1248
1249 (make-obsolete-variable 'autoload-target-directory
1250   "Don't use this.  Bind `generated-autoload-file' to an absolute path.")
1251 (make-obsolete 'batch-update-autoloads
1252                'autoload-update-directory-autoloads)
1253
1254 (provide 'autoload)
1255
1256 ;;; autoload.el ends here