+(defconst generate-autoload-section-continuation ";;;;;; "
+ "String to add on each continuation of the section header form.")
+
+(defun make-autoload (form file)
+ "Turn FORM into an autoload or defvar for source file FILE.
+Returns nil if FORM is not a special autoload form (i.e. a function definition
+or macro definition or a defcustom)."
+ (let ((car (car-safe form)) expand)
+ (cond
+ ;; For complex cases, try again on the macro-expansion.
+ ((and (memq car '(easy-mmode-define-global-mode
+ easy-mmode-define-minor-mode define-minor-mode))
+ (setq expand (let ((load-file-name file)) (macroexpand form)))
+ (eq (car expand) 'progn)
+ (memq :autoload-end expand))
+ (let ((end (memq :autoload-end expand)))
+ ;; Cut-off anything after the :autoload-end marker.
+ (setcdr end nil)
+ (cons 'progn
+ (mapcar (lambda (form) (make-autoload form file))
+ (cdr expand)))))
+
+ ;; For special function-like operators, use the `autoload' function.
+ ((memq car '(defun define-skeleton defmacro define-derived-mode
+ define-compilation-mode
+ define-generic-mode easy-mmode-define-minor-mode
+ easy-mmode-define-global-mode
+ define-minor-mode defun* defmacro*))
+ (let* ((macrop (memq car '(defmacro defmacro*)))
+ (name (nth 1 form))
+ (args (case car
+ ((defun defmacro defun* defmacro*) (nth 2 form))
+ ((define-skeleton) '(&optional str arg))
+ ((define-generic-mode define-derived-mode
+ define-compilation-mode) nil)
+ (t)))
+ (body (nthcdr (get car 'doc-string-elt) form))
+ (doc (if (stringp (car body)) (pop body))))
+ (when (listp args)
+ ;; Add the usage form at the end where describe-function-1
+ ;; can recover it.
+ (setq doc (help-add-fundoc-usage doc args)))
+ ;; `define-generic-mode' quotes the name, so take care of that
+ (list 'autoload (if (listp name) name (list 'quote name)) file doc
+ (or (and (memq car '(define-skeleton define-derived-mode
+ define-generic-mode
+ easy-mmode-define-global-mode
+ easy-mmode-define-minor-mode
+ define-minor-mode)) t)
+ (eq (car-safe (car body)) 'interactive))
+ (if macrop (list 'quote 'macro) nil))))
+
+ ;; Convert defcustom to less space-consuming data.
+ ((eq car 'defcustom)
+ (let ((varname (car-safe (cdr-safe form)))
+ (init (car-safe (cdr-safe (cdr-safe form))))
+ (doc (car-safe (cdr-safe (cdr-safe (cdr-safe form)))))
+ ;; (rest (cdr-safe (cdr-safe (cdr-safe (cdr-safe form)))))
+ )
+ `(progn
+ (defvar ,varname ,init ,doc)
+ (custom-autoload ',varname ,file))))
+
+ ;; nil here indicates that this is not a special autoload form.
+ (t nil))))
+
+;; Forms which have doc-strings which should be printed specially.
+;; A doc-string-elt property of ELT says that (nth ELT FORM) is
+;; the doc-string in FORM.
+;; Those properties are now set in lisp-mode.el.
+
+
+(defun autoload-trim-file-name (file)
+ ;; Returns a relative pathname of FILE
+ ;; starting from the directory that loaddefs.el is in.
+ ;; That is normally a directory in load-path,
+ ;; which means Emacs will be able to find FILE when it looks.
+ ;; Any extra directory names here would prevent finding the file.
+ (setq file (expand-file-name file))
+ (file-relative-name file
+ (file-name-directory generated-autoload-file)))
+
+(defun autoload-read-section-header ()
+ "Read a section header form.
+Since continuation lines have been marked as comments,
+we must copy the text of the form and remove those comment
+markers before we call `read'."
+ (save-match-data
+ (let ((beginning (point))
+ string)
+ (forward-line 1)
+ (while (looking-at generate-autoload-section-continuation)
+ (forward-line 1))
+ (setq string (buffer-substring beginning (point)))
+ (with-current-buffer (get-buffer-create " *autoload*")
+ (erase-buffer)
+ (insert string)
+ (goto-char (point-min))
+ (while (search-forward generate-autoload-section-continuation nil t)
+ (replace-match " "))
+ (goto-char (point-min))
+ (read (current-buffer))))))
+
+(defvar autoload-print-form-outbuf)
+
+(defun autoload-print-form (form)
+ "Print FORM such that `make-docfile' will find the docstrings.
+The variable `autoload-print-form-outbuf' specifies the buffer to
+put the output in."
+ (cond
+ ;; If the form is a sequence, recurse.
+ ((eq (car form) 'progn) (mapcar 'autoload-print-form (cdr form)))
+ ;; Symbols at the toplevel are meaningless.
+ ((symbolp form) nil)
+ (t
+ (let ((doc-string-elt (get (car-safe form) 'doc-string-elt))
+ (outbuf autoload-print-form-outbuf))
+ (if (and doc-string-elt (stringp (nth doc-string-elt form)))
+ ;; We need to hack the printing because the
+ ;; doc-string must be printed specially for
+ ;; make-docfile (sigh).
+ (let* ((p (nthcdr (1- doc-string-elt) form))
+ (elt (cdr p)))
+ (setcdr p nil)
+ (princ "\n(" outbuf)
+ (let ((print-escape-newlines t)
+ (print-escape-nonascii t))
+ (dolist (elt form)
+ (prin1 elt outbuf)
+ (princ " " outbuf)))
+ (princ "\"\\\n" outbuf)
+ (let ((begin (with-current-buffer outbuf (point))))
+ (princ (substring (prin1-to-string (car elt)) 1)
+ outbuf)
+ ;; Insert a backslash before each ( that
+ ;; appears at the beginning of a line in
+ ;; the doc string.
+ (with-current-buffer outbuf
+ (save-excursion
+ (while (re-search-backward "\n[[(]" begin t)
+ (forward-char 1)
+ (insert "\\"))))
+ (if (null (cdr elt))
+ (princ ")" outbuf)
+ (princ " " outbuf)
+ (princ (substring (prin1-to-string (cdr elt)) 1)
+ outbuf))
+ (terpri outbuf)))
+ (let ((print-escape-newlines t)
+ (print-escape-nonascii t))
+ (print form outbuf)))))))
+
+(defun autoload-ensure-default-file (file)
+ "Make sure that the autoload file FILE exists and if not create it."
+ (unless (file-exists-p file)
+ (write-region
+ (concat ";;; " (file-name-nondirectory file)
+ " --- automatically extracted autoloads\n"
+ ";;\n"
+ ";;; Code:\n\n"
+ "\f\n;; Local Variables:\n"
+ ";; version-control: never\n"
+ ";; no-byte-compile: t\n"
+ ";; no-update-autoloads: t\n"
+ ";; End:\n"
+ ";;; " (file-name-nondirectory file)
+ " ends here\n")
+ nil file))
+ file)
+
+(defun autoload-insert-section-header (outbuf autoloads load-name file time)
+ "Insert the section-header line,
+which lists the file name and which functions are in it, etc."
+ (insert generate-autoload-section-header)
+ (prin1 (list 'autoloads autoloads load-name
+ (if (stringp file) (autoload-trim-file-name file) file)
+ time)
+ outbuf)
+ (terpri outbuf)
+ ;; Break that line at spaces, to avoid very long lines.
+ ;; Make each sub-line into a comment.
+ (with-current-buffer outbuf
+ (save-excursion
+ (forward-line -1)
+ (while (not (eolp))
+ (move-to-column 64)
+ (skip-chars-forward "^ \n")
+ (or (eolp)
+ (insert "\n" generate-autoload-section-continuation))))))