Remove superfluous pointer check which seems to trigger
[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           (t
555            (princ (buffer-substring
556                    (progn
557                      ;; Back up over whitespace, to preserve it.
558                      (skip-chars-backward " \f\t")
559                      (if (= (char-after (1+ (point))) ? )
560                          ;; Eat one space.
561                          (forward-char 1))
562                      (point))
563                    (progn (forward-line 1) (point)))
564                   outbuf))))
565   autoloads-done)
566
567 (defun* generate-lisp-file-autoloads-1 (outbuf load-name trim-name)
568   "Insert at point in OUTBUF an autoload section for an Elisp file.
569 The file is assumed to be already loaded and in the current buffer.
570 autoloads are generated for defuns and defmacros marked by
571 `generate-autoload-cookie' (which see)."
572   (let ((autoloads-done '())
573         )
574     (save-excursion
575       (save-restriction
576         (widen)
577         (goto-char (point-min))
578         (unless (search-forward generate-autoload-cookie nil t)
579           (message "No autoloads found in %s" trim-name)
580           (return-from generate-lisp-file-autoloads-1 nil))
581
582         (message "Generating autoloads for %s..." trim-name)
583         (goto-char (point-min))
584         (while (not (eobp))
585           (skip-chars-forward " \t\n\f")
586           (cond
587            ((looking-at (regexp-quote generate-autoload-cookie))
588             (search-forward generate-autoload-cookie)
589             (setq autoloads-done
590                   (process-one-lisp-autoload autoloads-done outbuf load-name)))
591            ((looking-at ";")
592             ;; Don't read the comment.
593             (forward-line 1))
594            (t
595             (forward-sexp 1)
596             (forward-line 1)))
597           )))
598     (or noninteractive ; XEmacs: only need one line in -batch mode.
599         (message "Generating autoloads for %s...done" trim-name))
600     autoloads-done))
601
602 (defun* generate-c-file-autoloads-1 (outbuf load-name trim-name
603                                      &optional funlist)
604   "Insert at point an autoload section for the C file FILE.
605 autoloads are generated for defuns and defmacros in FILE
606 marked by `generate-c-autoload-cookie' (which see).
607 If FILE is being visited in a buffer, the contents of the buffer
608 are used."
609   (let (autoloads-done)
610     (save-excursion
611       (save-restriction
612         (widen)
613         (goto-char (point-min))
614         ;; Is there a module name comment?
615         (when (search-forward generate-c-autoload-module nil t)
616           (skip-chars-forward " \t")
617           (let ((begin (point)))
618             (skip-chars-forward "^ \t\n\f")
619             (setq load-name (buffer-substring begin (point)))))
620         (if funlist
621             (progn
622               (message "Generating autoloads for %s..." trim-name)
623               (dolist (arg funlist)
624                 (goto-char (point-min))
625                 (re-search-forward
626                  (concat "DEFUN (\""
627                          (regexp-quote (symbol-name arg))
628                          "\""))
629                 (goto-char (match-beginning 0))
630                 (let ((autoload (make-c-autoload load-name)))
631                   (when autoload
632                     (push (nth 1 (nth 1 autoload)) autoloads-done)
633                     (autoload-print-form autoload outbuf "")))))
634           (goto-char (point-min))
635           (let ((match
636                  (search-forward generate-c-autoload-cookie nil t)))
637             (unless match
638               (message "No autoloads found in %s" trim-name)
639               (return-from generate-c-file-autoloads-1 nil))
640             (message "Generating autoloads for %s..." trim-name)
641             (while match
642               (forward-line 1)
643               (let ((autoload (make-c-autoload load-name)))
644                 (when autoload
645                   (push (nth 1 (nth 1 autoload)) autoloads-done)
646                   (autoload-print-form autoload outbuf "")))
647               (setq match
648                     (search-forward generate-c-autoload-cookie nil t)))))))
649     (or noninteractive ; XEmacs: only need one line in -batch mode.
650         (message "Generating autoloads for %s...done" trim-name))
651     autoloads-done))
652
653 ;;;###autoload
654 (defun generate-custom-defines (file)
655   "Insert at point a custom-define section for FILE.
656 If FILE is being visited in a buffer, the contents of the buffer
657 are used."
658   (interactive "fGenerate custom defines for file: ")
659   (cond ((string-match "\\.el$" file)
660          (generate-autoload-type-section
661           file
662           (replace-in-string (file-name-nondirectory file) "\\.elc?$" "")
663           nil #'generate-custom-defines-1))
664         ((string-match "\\.c$" file)
665          ;; no way to generate custom-defines for C files (currently?),
666          ;; but cannot signal an error.
667          nil)
668         (t
669          (error 'wrong-type-argument file "not a C or Elisp source file"))))
670
671 (defun* generate-custom-defines-1 (outbuf load-name trim-name)
672   "Insert at point in OUTBUF a custom-define section for an Elisp file.
673 This contains all defcustoms and defgroups in the file.
674 The file is assumed to be already loaded and in the current buffer."
675   (let* ((search-regexp-1 "^(\\(defcustom\\|defgroup\\) ")
676          (search-string-2 ";;;###custom-define")
677          (search-regexp-2 (regexp-quote search-string-2))
678          (autoloads-done '()))
679     (save-excursion
680       (save-restriction
681         (widen)
682         (goto-char (point-min))
683         (unless (or (re-search-forward search-regexp-1 nil t)
684                     (re-search-forward search-regexp-2 nil t))
685           (message "No custom defines found in %s" trim-name)
686           (return-from generate-custom-defines-1 nil))
687         (message "Generating custom defines for %s..." trim-name)
688         (princ "(defconst custom-define-current-source-file " outbuf)
689         (prin1 (file-relative-name (buffer-file-name)
690                                    (symbol-value-in-buffer 'default-directory
691                                                            outbuf)) outbuf)
692         (princ ")\n" outbuf)
693                
694         (goto-char (point-min))
695         (while (not (eobp))
696           (skip-chars-forward " \t\n\f")
697           (cond
698            ((looking-at search-regexp-1)
699             ;; Read the next form and copy it to make an autoload.
700             (let* ((form (prog1 (read (current-buffer))
701                            (or (bolp) (forward-line 1))))
702                    (autoload form ;(make-autoload form load-name)
703                      ))
704               (if autoload
705                   (setq autoloads-done (cons (nth 1 form)
706                                              autoloads-done))
707                 (setq autoload form))
708               (autoload-print-form autoload outbuf ""))
709             )
710            ((looking-at search-regexp-2)
711             (search-forward search-string-2)
712             (beep)
713             (setq autoloads-done
714                   (process-one-lisp-autoload autoloads-done outbuf load-name)))
715            ((looking-at ";")
716             ;; Don't read the comment.
717             (forward-line 1))
718            (t
719             (forward-sexp 1)
720             (forward-line 1)))
721           )))
722     (or noninteractive ; XEmacs: only need one line in -batch mode.
723         (message "Generating custom defines for %s...done" trim-name))
724     autoloads-done))
725
726 ;; Assorted utilities for generating autoloads and pieces thereof
727
728 (defun autoload-print-form (form outbuf margin)
729   "Print an autoload form, handling special characters.
730 In particular, print docstrings with escapes inserted before left parentheses
731 at the beginning of lines and ^L characters."
732   (cond
733    ;; If the form is a sequence, recurse.
734    ((eq (car form) 'progn)
735     (mapcar #'(lambda (x) (autoload-print-form x outbuf margin))
736             (cdr form)))
737    ;; Symbols at the toplevel are meaningless.
738    ((symbolp form) nil)
739    (t
740     (let ((doc-string-elt (get (car-safe form) 'doc-string-elt)))
741       (if (and doc-string-elt (stringp (nth doc-string-elt form)))
742           ;; We need to hack the printing because the doc-string must be
743           ;; printed specially for make-docfile (sigh).
744           (let* ((p (nthcdr (1- doc-string-elt) form))
745                  (elt (cdr p))
746                  (start-string (format "\n%s(" margin)))
747             (setcdr p nil)
748             (princ start-string outbuf)
749             ;; XEmacs change: don't let ^^L's get into
750             ;; the file or sorting is hard.
751             (let ((print-escape-newlines t)
752                   ;;#### FSF 21.2 (print-escape-nonascii t)
753                   (p (point outbuf))
754                   p2)
755               (mapcar #'(lambda (elt)
756                           (prin1 elt outbuf)
757                           (princ " " outbuf))
758                       form)
759               (with-current-buffer outbuf
760                 (setq p2 (point-marker))
761                 (goto-char p)
762                 (save-match-data
763                   (while (search-forward "\^L" p2 t)
764                     (delete-char -1)
765                     (insert "\\^L")))
766                 (goto-char p2)))
767             (princ "\"\\\n" outbuf)
768             (let ((begin (point outbuf)))
769               (princ (substring (prin1-to-string (car elt)) 1) outbuf)
770               ;; Insert a backslash before each ( that appears at the beginning
771               ;; of a line in the doc string.
772               (with-current-buffer outbuf
773                 (save-excursion
774                   (while (search-backward start-string begin t)
775                     (forward-char 1)
776                     (insert "\\"))))
777               (if (null (cdr elt))
778                   (princ ")" outbuf)
779                 (princ " " outbuf)
780                 (princ (substring (prin1-to-string (cdr elt)) 1) outbuf))
781               (terpri outbuf)
782               (princ margin outbuf)))
783         ;; XEmacs change: another ^L hack
784         (let ((p (point outbuf))
785               (print-escape-newlines t)
786               ;;#### FSF 21.2 (print-escape-nonascii t)
787               p2)
788           (print form outbuf)
789           (with-current-buffer outbuf
790             (setq p2 (point-marker))
791             (goto-char p)
792             (save-match-data
793               (while (search-forward "\^L" p2 t)
794                 (delete-char -1)
795                 (insert "\\^L")))
796             (goto-char p2))))))))
797
798 ;;; Forms which have doc-strings which should be printed specially.
799 ;;; A doc-string-elt property of ELT says that (nth ELT FORM) is
800 ;;; the doc-string in FORM.
801 ;;;
802 ;;; There used to be the following note here:
803 ;;; ;;; Note: defconst and defvar should NOT be marked in this way.
804 ;;; ;;; We don't want to produce defconsts and defvars that
805 ;;; ;;; make-docfile can grok, because then it would grok them twice,
806 ;;; ;;; once in foo.el (where they are given with ;;;###autoload) and
807 ;;; ;;; once in loaddefs.el.
808 ;;;
809 ;;; Counter-note: Yes, they should be marked in this way.
810 ;;; make-docfile only processes those files that are loaded into the
811 ;;; dumped Emacs, and those files should never have anything
812 ;;; autoloaded here.  The above-feared problem only occurs with files
813 ;;; which have autoloaded entries *and* are processed by make-docfile;
814 ;;; there should be no such files.
815
816 (put 'autoload 'doc-string-elt 3)
817 (put 'defun    'doc-string-elt 3)
818 (put 'defun*   'doc-string-elt 3)
819 (put 'defvar   'doc-string-elt 3)
820 (put 'defcustom 'doc-string-elt 3)
821 (put 'defconst 'doc-string-elt 3)
822 (put 'defmacro 'doc-string-elt 3)
823 (put 'defmacro* 'doc-string-elt 3)
824 (put 'defsubst 'doc-string-elt 3)
825 (put 'define-skeleton 'doc-string-elt 2)
826 (put 'define-derived-mode 'doc-string-elt 4)
827 (put 'easy-mmode-define-minor-mode 'doc-string-elt 2)
828 (put 'define-minor-mode 'doc-string-elt 2)
829 (put 'define-generic-mode 'doc-string-elt 7)
830 ;; defin-global-mode has no explicit docstring.
831 (put 'easy-mmode-define-global-mode 'doc-string-elt 1000)
832
833 (defun autoload-trim-file-name (file)
834   "Returns relative pathname of FILE including the last directory."
835   (setq file (expand-file-name file))
836   (file-relative-name file (file-name-directory
837                             (directory-file-name
838                              (file-name-directory file)))))
839
840 (defun autoload-read-section-header ()
841   "Read a section header form.
842 Since continuation lines have been marked as comments,
843 we must copy the text of the form and remove those comment
844 markers before we call `read'."
845   (save-match-data
846     (let ((beginning (point))
847           string)
848       (forward-line 1)
849       (while (looking-at generate-autoload-section-continuation)
850         (forward-line 1))
851       (setq string (buffer-substring beginning (point)))
852       (with-current-buffer (get-buffer-create " *autoload*")
853         (erase-buffer)
854         (insert string)
855         (goto-char (point-min))
856         (while (search-forward generate-autoload-section-continuation nil t)
857           (replace-match " "))
858         (goto-char (point-min))
859         (read (current-buffer))))))
860
861 ;;;###autoload
862 (defun update-file-autoloads (file)
863   "Update the autoloads for FILE in `generated-autoload-file'
864 \(which FILE might bind in its local variables).
865 This function is a no-op for an autoloads file (ie, a file whose name is
866 equal to `autoload-file-name')."
867   (interactive "fUpdate autoloads for file: ")
868   (setq file (expand-file-name file))
869   (when (and (file-newer-than-file-p file generated-autoload-file)
870              (not (member (file-name-nondirectory file)
871                           (list autoload-file-name))))
872
873     (let ((load-name (replace-in-string (file-name-nondirectory file)
874                                         "\\.\\(elc?\\|c\\)$"
875                                         ""))
876           (trim-name (autoload-trim-file-name file))
877           section-begin form)
878       (save-excursion
879         ;; FSF has: [[ We want to get a value for generated-autoload-file
880         ;; from the local variables section if it's there. ]] Not
881         ;; applicable in XEmacs, since we always keep the autoloads
882         ;; up-to-date.
883
884         ;; #### FSF 21.2 adds: [[ We must read/write the file without any
885         ;; code conversion, but still decode EOLs. ]] Not clear if we need
886         ;; this. --ben
887         ;; (let ((coding-system-for-read 'raw-text))
888         (let ((find-file-hooks nil))
889           (set-buffer (or (get-file-buffer generated-autoload-file)
890                           (find-file-noselect generated-autoload-file))))
891         ;; FSF 21.2 says:
892
893         ;; [[ This is to make generated-autoload-file have Unix EOLs, so
894         ;; that it is portable to all platforms. ]]
895         ;; (setq buffer-file-coding-system 'raw-text-unix))
896         ;; Not applicable in XEmacs, since we always keep the autoloads
897         ;; up-to-date and recompile when we build.
898
899         ;; FSF 21.2: [not applicable to XEmacs]
900 ;       (or (> (buffer-size) 0)
901 ;           (error "Autoloads file %s does not exist" buffer-file-name))
902 ;       (or (file-writable-p buffer-file-name)
903 ;           (error "Autoloads file %s is not writable" buffer-file-name))
904
905         ;; NOTE: The rest of this function is totally changed from FSF.
906         ;; Hence, not synched.
907
908         ;; Make sure we can scribble in it.
909         (setq buffer-read-only nil)
910         ;; First delete all sections for this file.
911         (goto-char (point-min))
912         (while (search-forward generate-autoload-section-header nil t)
913           (setq section-begin (match-beginning 0))
914           (setq form (autoload-read-section-header))
915           (when (string= (nth 2 form) load-name)
916             (search-forward generate-autoload-section-trailer)
917             (delete-region section-begin (point))))
918
919         ;; Now find insertion point for new section
920         (block find-insertion-point
921           (goto-char (point-min))
922           (while (search-forward generate-autoload-section-header nil t)
923             (setq form (autoload-read-section-header))
924             (when (string< trim-name (nth 3 form))
925               ;; Found alphabetically correct insertion point
926               (goto-char (match-beginning 0))
927               (return-from find-insertion-point))
928             (search-forward generate-autoload-section-trailer))
929           (when (eq (point) (point-min))        ; No existing entries?
930             (goto-char (point-max))))   ; Append.
931
932         ;; Add in new sections for file
933         (funcall generate-autoload-function file))
934
935       (when (interactive-p) (save-buffer)))))
936
937 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
938 ;; Utilities for batch updates
939
940 (defun parse-command-line (cmdl)
941   (let ((newcmdl (dllist))
942         (cmdlpl (make-skiplist))
943         (mm (compile-regexp "^--"))
944         (ign (compile-regexp #r"^-\(?:batch\|nd\|vanilla\)"))
945         (ign2 (compile-regexp "^-[lf]$")))
946     (while (car cmdl)
947       (cond ((string-match mm (car cmdl))
948              (let ((key (intern (car cmdl)))
949                    (val (car (cdr-safe cmdl))))
950                (put-skiplist cmdlpl key val)
951                (setq cmdl (cdr-safe cmdl))))
952             ((string-match ign2 (car cmdl))
953              ;; ignore a pair of parameters
954              (setq cmdl (cdr-safe cmdl)))
955             ((string-match ign (car cmdl))
956              ;; ignore this single parameter
957              )
958             (t
959              (dllist-append newcmdl (car cmdl))))
960       (setq cmdl (cdr-safe cmdl)))
961     (put newcmdl :tweaks cmdlpl)
962     newcmdl))
963
964 ;;;###autoload
965 (defun batch-create-autoloads ()
966   "Update the autoloads for one or more directories.
967
968 #### The API and semantics of this function are subject to change."
969   (unless noninteractive
970     (error "batch-update-directory-autoloads: may be used only with -batch"))
971
972   (let* ((cmds (parse-command-line (cdr-safe command-line-args)))
973          (pl (get cmds :tweaks)))
974
975     (unless (get-skiplist pl '--autoload-dir-name)
976       (put-skiplist pl '--autoload-dir-name
977                     (expand-file-name default-directory)))
978     (unless (get-skiplist pl '--autoload-file-name)
979       (put-skiplist pl '--autoload-file-name
980                     (expand-file-name autoload-file-name
981                                       (get-skiplist pl '--autoload-dir-name))))
982     (unless (get-skiplist pl '--feature-prefix)
983       (put-skiplist pl '--feature-prefix
984                     (file-name-nondirectory
985                      (directory-file-name
986                       (expand-file-name
987                        (get-skiplist pl '--autoload-dir-name))))))
988
989     (create-autoload-files cmds t)))
990
991 (defun create-autoload-files (bunch &optional force)
992   (let* ((pl (get bunch :tweaks))
993          (relative (get-skiplist pl '--relative-to))
994          (al-file (get-skiplist pl '--autoload-file-name))
995          (fprefix (get-skiplist pl '--feature-prefix)))
996     (mapc-inplace
997      #'(lambda (dir)
998          (expand-file-name dir relative))
999      bunch)
1000     (update-autoload-files (dllist-to-list bunch) fprefix al-file force)))
1001
1002 ;;;###autoload
1003 (defun batch-update-directory-autoloads ()
1004   "Update the autoloads for a directory, using a specified feature prefix.
1005 Must be used only with -batch.  The feature prefix and directory to update
1006 are taken from the first and second elements of `command-line-args-left',
1007 respectively, and they are then removed from `command-line-args-left'.
1008
1009 Runs `update-file-autoloads' on each file in the given directory.  Always
1010 rewrites the autoloads file, even if unchanged.  Makes a feature name by
1011 applying `autoload-make-feature-name' to the specified feature prefix.
1012
1013 #### The API and semantics of this function are subject to change."
1014   (unless noninteractive
1015     (error "batch-update-directory-autoloads: may be used only with -batch"))
1016   (update-autoload-files (list (cadr command-line-args-left))
1017                          (car command-line-args-left) nil t)
1018   (setq command-line-args-left (cddr command-line-args-left)))
1019
1020 ;;;###autoload
1021 (defun batch-update-directory-custom-defines ()
1022   "Update the custom defines for a directory, using a specified feature prefix.
1023 Must be used only with -batch.  The feature prefix and directory to update
1024 are taken from the first and second elements of `command-line-args-left',
1025 respectively, and they are then removed from `command-line-args-left'.
1026
1027 Runs `update-file-autoloads' on each file in the given directory.  Always
1028 rewrites the autoloads file, even if unchanged.  Makes a feature name by
1029 applying `autoload-make-feature-name' to the specified feature prefix.
1030
1031 #### The API and semantics of this function are subject to change."
1032   (unless noninteractive
1033     (error "batch-update-directory-custom-defines: may be used only with -batch"))
1034   (update-custom-define-files (list (cadr command-line-args-left))
1035                               (car command-line-args-left) nil t)
1036   (setq command-line-args-left (cddr command-line-args-left)))
1037
1038 ;;;###autoload
1039 (defun update-autoload-files (files-or-dirs feature-prefix
1040                               &optional into-file force)
1041   "Update all the autoload files associated with FILES-OR-DIRS.
1042 FILES-OR-DIRS is a list of files and/or directories to be processed.
1043
1044 An appropriate autoload file is chosen and a feature constructed for
1045 each element of FILES-OR-DIRS.  Fixup code testing for the autoload file's
1046 feature and to provide the feature is added.
1047
1048 If optional INTO-FILE is non-`nil', it should specify a file into which
1049 the autoloads will be placed.  Otherwise, the autoloads will be placed into
1050 a file named `auto-autoloads.el' in the directory of each element in
1051 FILES-OR-DIRS.
1052
1053 FEATURE-PREFIX should be set to an appropriate prefix which will
1054 be concatenated with \"-autoloads\" to produce the feature name.  Otherwise
1055 the appropriate autoload file for each file or directory (located in that
1056 directory, or in the directory of the specified file) will be updated with
1057 the directory's or file's autoloads and the protective forms will be added,
1058 and the files will be saved.  Use of the default here is unreliable, and
1059 therefore deprecated.
1060
1061 Note that if some of FILES-OR-DIRS are directories, recursion goes only
1062 one level deep.
1063
1064 If FORCE is non-nil, always save out the autoload files even if unchanged."
1065   (or (listp files-or-dirs) (setq files-or-dirs (list files-or-dirs)))
1066   (let ((defdir (directory-file-name default-directory))
1067         ;; value for all-into-one-file
1068         (autoload-feature-name (autoload-make-feature-name feature-prefix))
1069         (enable-local-eval nil) ; Don't query in batch mode.
1070         (autoload-feature-prefix feature-prefix)
1071         ;; protect from change
1072         (generated-autoload-file generated-autoload-file))
1073     (dolist (arg files-or-dirs)
1074       (setq arg (expand-file-name arg defdir))
1075       (cond
1076        ((file-directory-p arg)
1077         (setq generated-autoload-file
1078               (or into-file (expand-file-name autoload-file-name arg)))
1079         (message "Updating autoloads for directory %s..." arg)
1080         (let ((simple-dir (file-name-as-directory
1081                            (file-name-nondirectory
1082                             (directory-file-name arg))))
1083               (enable-local-eval nil))
1084           (save-excursion
1085             (let ((find-file-hooks nil))
1086               (set-buffer (find-file-noselect generated-autoload-file)))
1087             (goto-char (point-min))
1088             (while (search-forward generate-autoload-section-header nil t)
1089               (let* ((begin (match-beginning 0))
1090                      (form (autoload-read-section-header))
1091                      (file (nth 3 form)))
1092                 (when (and (stringp file)
1093                            (string= (file-name-directory file) simple-dir)
1094                            (not (file-exists-p
1095                                  (expand-file-name
1096                                   (file-name-nondirectory file) arg))))
1097                   ;; Remove the obsolete section.
1098                   (search-forward generate-autoload-section-trailer)
1099                   (delete-region begin (point)))))
1100             ;; Update or create autoload sections for existing files.
1101             (mapcar 'update-file-autoloads
1102                     (directory-files arg t "^[^=].*\\.\\(el\\|c\\)$")))))
1103        ((file-exists-p arg)
1104         (setq generated-autoload-file
1105               (or into-file (expand-file-name autoload-file-name
1106                                               (file-name-directory arg))))
1107         (update-file-autoloads arg))
1108        (t (error "No such file or directory: %s" arg)))
1109       (when (not into-file)
1110         (autoload-featurep-protect-autoloads
1111          (autoload-make-feature-name
1112           (or feature-prefix
1113               (file-name-nondirectory (directory-file-name arg)))))
1114         (if force (set-buffer-modified-p
1115                    t (find-file-noselect generated-autoload-file)))))
1116     (when into-file
1117       (autoload-featurep-protect-autoloads autoload-feature-name)
1118       (if force (set-buffer-modified-p
1119                  t (find-file-noselect into-file))))
1120     (save-some-buffers t)
1121     ))
1122
1123 ;;;###autoload
1124 (defun update-custom-define-files (files-or-dirs feature-prefix
1125                                    &optional into-file force)
1126   "Update all the custom-define files associated with FILES-OR-DIRS.
1127 Works just like `update-file-autoloads'."
1128   (let* ((autoload-feature-suffix "-custom-defines")
1129          (autoload-file-name "custom-defines.el")
1130          (generate-autoload-function #'generate-custom-defines))
1131     (update-autoload-files files-or-dirs feature-prefix into-file force)))
1132
1133 (defun autoload-featurep-protect-autoloads (sym)
1134   (save-excursion
1135     (set-buffer (find-file-noselect generated-autoload-file))
1136     (goto-char (point-min))
1137     (cond ((eq (point-min) (point-max)) nil)
1138           ;; if there's some junk in the file but no sections, just
1139           ;; delete everything.  the junk might be stuff inserted by
1140           ;; an older version of this function.
1141           ((not (search-forward generate-autoload-section-header nil t))
1142            (delete-region (point-min) (point-max)))
1143           (t
1144            (goto-char (point-min))
1145            (when (looking-at ";;; DO NOT MODIFY THIS FILE")
1146              (delete-region (point-min)
1147                             (progn
1148                               (search-forward generate-autoload-section-header)
1149                               (match-beginning 0))))
1150            ;; Determine and set the coding system for the file if under Mule.
1151            ;; If there are any extended characters in the input file, use
1152            ;; `escape-quoted' to make sure that both binary and extended
1153            ;; characters are output properly and distinguished properly.
1154            ;; Otherwise, use `raw-text' for maximum portability with non-Mule
1155            ;; Emacsen.
1156            (if (or (featurep '(not mule)) ;; Don't scan if no Mule support
1157                    (progn
1158                      (goto-char (point-min))
1159                      ;; mrb- There must be a better way than skip-chars-forward
1160                      (skip-chars-forward (concat (char-to-string 0) "-"
1161                                                  (char-to-string 255)))
1162                      (eq (point) (point-max))))
1163                (setq buffer-file-coding-system 'raw-text-unix)
1164              (setq buffer-file-coding-system 'escape-quoted))
1165            (goto-char (point-min))
1166            (insert ";;; DO NOT MODIFY THIS FILE")
1167            ;; NOTE: XEmacs prior to 21.5.12 or so had a bug in that it
1168            ;; recognized only one of the two magic-cookie styles (the -*- kind)
1169            ;; in find-file, but both of them in load.  We go ahead and put both
1170            ;; in, just to be safe.
1171            (when (eq buffer-file-coding-system 'escape-quoted)
1172              (insert " -*- coding: escape-quoted; -*-
1173 \(or (featurep 'mule) (error \"Loading this file requires Mule support\"))
1174 ;;;###coding system: escape-quoted"))
1175            (insert "\n(if (featurep '" sym ")")
1176            (insert " (error \"Feature " sym " already loaded\"))\n")
1177            (goto-char (point-max))
1178            (save-excursion
1179              (forward-line -1)
1180              (when (looking-at "(provide")
1181                (delete-region (point) (point-max))))
1182            (unless (bolp) (insert "\n"))
1183            (unless (eq (char-before (1- (point))) ?\^L)
1184              (insert "\^L\n"))
1185            (insert "(provide '" sym ")\n")))))
1186
1187 (defun autoload-make-feature-name (&optional prefix)
1188   "Generate the feature name to protect this auto-autoloads file from PREFIX.
1189
1190 If PREFIX is nil, it defaults to the value of `autoload-feature-prefix' if
1191 that is non-nil.
1192
1193 The feature name must be globally unique for this version of XEmacs,
1194 including packages.
1195
1196 For backward compatibility, if PREFIX and `autoload-feature-prefix' are both
1197 `nil', PREFIX is computed as the last directory component of
1198 `generated-autoload-file'.  This is likely to result in non-uniqueness, so
1199 do not use this feature."
1200   (concat
1201    (cond (prefix)
1202          (autoload-feature-prefix)
1203          ((stringp generated-autoload-file)
1204           (message "Warning: autoload computing feature prefix.
1205 You should specify it as an argument to `autoload-make-feature-name'.")
1206           (file-name-nondirectory
1207            (directory-file-name
1208             (file-name-directory generated-autoload-file))))
1209          (t (error 'invalid-argument
1210                    "Could not compute a feature name")))
1211    autoload-feature-suffix))
1212
1213 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1214 ;; Deprecated entry points
1215
1216 ;; A grep of the core and packages shows use of `batch-update-autoloads'
1217 ;; by XEmacs.rules, pcomplete, eshell, oort-gnus; `batch-update-directory'
1218 ;; by liece.  The other two entry points (`batch-update-one-directory',
1219 ;; `batch-force-update-one-directory') were not used at all.
1220 ;;
1221 ;; All except the first are now history.  liece has been updated.
1222 ;; XEmacs.rules has been updated.  The others will be, eventually.
1223
1224 ;; There don't seem to be very many packages that use the first one (the
1225 ;; "all-into-one-file" variety), and do they actually rely on this
1226 ;; functionality? --ben
1227
1228 ;; but XEmacs.rules does, though maybe it doesn't "rely" on it, and
1229 ;; modules do now, and that relies on it. --sjt
1230
1231 ;;;###autoload
1232 (defun batch-update-autoloads ()
1233   "Update the autoloads for the files or directories on the command line.
1234 Runs `update-file-autoloads' on files and `update-directory-autoloads'
1235 on directories.  Must be used only with -batch, and kills Emacs on completion.
1236 Each file will be processed even if an error occurred previously.
1237 For example, invoke `xemacs -batch -f batch-update-autoloads *.el'.
1238 The directory to which the auto-autoloads.el file must be the first parameter
1239 on the command line."
1240   (unless noninteractive
1241     (error "batch-update-autoloads is to be used only with -batch"))
1242   (update-autoload-files command-line-args-left autoload-feature-prefix
1243                          generated-autoload-file t)
1244   (kill-emacs 0))
1245
1246 ;; Declare obsolescence
1247
1248 (make-obsolete-variable 'autoload-target-directory
1249   "Don't use this.  Bind `generated-autoload-file' to an absolute path.")
1250 (make-obsolete 'batch-update-autoloads
1251                'autoload-update-directory-autoloads)
1252
1253 (provide 'autoload)
1254
1255 ;;; autoload.el ends here