# HG changeset patch # User ben # Date 1107414688 0 # Node ID c4c8a36043becba50a87fd532574f095aa5abbf6 # Parent a9527fcdf77f73a7be3acf2f133e38f763f5c036 [xemacs-hg @ 2005-02-03 07:11:19 by ben] behavior ws #4: package-suppress, autoload update/sync, add easy-mmode/regexp-opt to core lread.c, lisp.h: Remove undeeded Vload_file_name_internal_the_purecopy, Qload_file_name -- use internal_bind_lisp_object instead of specbind. Add load-suppress-alist. * easy-mmode.el, regexp-opt.el: Move these files into core. Uncomment stuff depending on new custom.el. autoload.el: Removed. Major update. Sync with FSF 21.2. Create the ability to make custom-defines files. update-elc-2.el, update-elc.el: Rewrite to use new autoload API. update-elc.el: Add easy-mmode. diff -r a9527fcdf77f -r c4c8a36043be lisp/ChangeLog --- a/lisp/ChangeLog Thu Feb 03 06:14:40 2005 +0000 +++ b/lisp/ChangeLog Thu Feb 03 07:11:28 2005 +0000 @@ -1,3 +1,48 @@ +2005-02-02 Ben Wing + + * easy-mmode.el, regexp-opt.el: + Move these files into core. + Uncomment stuff depending on new custom.el. + + * autoload.el: + * autoload.el (generate-autoload-function): New. + * autoload.el (autoload-feature-suffix): New. + * autoload.el (generate-autoload-section-continuation): New. + * autoload.el (make-autoload): + * autoload.el (generate-file-autoloads): + * autoload.el (generate-autoload-type-section): + * autoload.el (process-one-lisp-autoload): New. + * autoload.el (generate-lisp-file-autoloads-1): + * autoload.el (generate-c-file-autoloads-1): + * autoload.el (generate-custom-defines): New. + * autoload.el (print-autoload): Removed. + * autoload.el (autoload-print-form): New. + * autoload.el (defcustom): + * autoload.el (autoload-read-section-header): New. + * autoload.el (update-file-autoloads): + * autoload.el (update-autoloads-here): Removed. + * autoload.el (batch-update-directory-custom-defines): New. + * autoload.el (update-autoload-files): + * autoload.el (autoload-update-directory-autoloads): Removed. + * autoload.el (batch-update-directory-autoloads): New. + * autoload.el (autoload-featurep-protect-autoloads): + * autoload.el (update-autoloads-from-directory): Removed. + * autoload.el (update-custom-define-files): New. + * autoload.el (autoload-make-feature-name): + * autoload.el (batch-update-autoloads): + * autoload.el (batch-update-directory): Removed. + * autoload.el (batch-update-one-directory): Removed. + * autoload.el (batch-force-update-one-directory): Removed. + Major update. Sync with FSF 21.2. + Create the ability to make custom-defines files. + + * update-elc-2.el (batch-update-elc-2): + * update-elc.el (do-autoload-commands): + Rewrite to use new autoload API. + + * update-elc.el (lisp-files-needing-early-byte-compilation): + Add easy-mmode. + 2005-02-02 Ben Wing * behavior.el: @@ -207,42 +252,6 @@ 2004-11-09 Ben Wing - * easy-mmode.el, regexp-opt.el: - Move these files into core. - Uncomment stuff depending on new custom.el. - - * autoload.el: - * autoload.el (generate-autoload-function): New. - * autoload.el (autoload-feature-suffix): New. - * autoload.el (generate-autoload-section-continuation): New. - * autoload.el (make-autoload): - * autoload.el (generate-file-autoloads): - * autoload.el (generate-autoload-type-section): - * autoload.el (process-one-lisp-autoload): New. - * autoload.el (generate-lisp-file-autoloads-1): - * autoload.el (generate-c-file-autoloads-1): - * autoload.el (generate-custom-defines): New. - * autoload.el (print-autoload): Removed. - * autoload.el (autoload-print-form): New. - * autoload.el (defcustom): - * autoload.el (autoload-read-section-header): New. - * autoload.el (update-file-autoloads): - * autoload.el (update-autoloads-here): Removed. - * autoload.el (batch-update-directory-custom-defines): New. - * autoload.el (update-autoload-files): - * autoload.el (autoload-update-directory-autoloads): Removed. - * autoload.el (batch-update-directory-autoloads): New. - * autoload.el (autoload-featurep-protect-autoloads): - * autoload.el (update-autoloads-from-directory): Removed. - * autoload.el (update-custom-define-files): New. - * autoload.el (autoload-make-feature-name): - * autoload.el (batch-update-autoloads): - * autoload.el (batch-update-directory): Removed. - * autoload.el (batch-update-one-directory): Removed. - * autoload.el (batch-force-update-one-directory): Removed. - Major update. Sync with FSF 21.2. - Create the ability to make custom-defines files. - * paragraphs.el: * paragraphs.el (paragraphs): New. * paragraphs.el (use-hard-newlines): Removed. @@ -259,12 +268,6 @@ * paragraphs.el (transpose-sentences): Sync to 21.3. Depends on easy-mmode in core. - * update-elc-2.el (batch-update-elc-2): - * update-elc.el (do-autoload-commands): - Rewrite to use new autoload API. - - * update-elc.el (lisp-files-needing-early-byte-compilation): - Add easy-mmode. 2005-01-31 Ben Wing diff -r a9527fcdf77f -r c4c8a36043be lisp/autoload.el --- a/lisp/autoload.el Thu Feb 03 06:14:40 2005 +0000 +++ b/lisp/autoload.el Thu Feb 03 07:11:28 2005 +0000 @@ -2,9 +2,10 @@ ;; Copyright (C) 1991-1994, 1997, 2003 Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. -;; Copyright (C) 1996, 2000, 2002, 2003 Ben Wing. +;; Copyright (C) 1996, 2000, 2002, 2003, 2004 Ben Wing. -;; Author: Roland McGrath +;; Original Author: Roland McGrath +;; Heavily Modified: XEmacs Maintainers ;; Keywords: maint ;; This file is part of XEmacs. @@ -24,13 +25,17 @@ ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;; 02111-1307, USA. -;;; Synched up with: Not synched with FSF. +;;; Synched up with: FSF 21.2 by Ben Wing. +;;; Note that update-file-autoloads is seriously modified and not really +;;; syncable. ;;; Commentary: ;; This code keeps auto-autoloads.el files up to date. It interprets ;; magic cookies (of the form ";;;###autoload" in Lisp source files ;; and "/* ###autoload */" in C source files) in various useful ways. +;; It is also used to maintain custom-defines.el files, since most of +;; the logic for computing them is the same as for auto-autoloads.el. ;; Usage ;; ===== @@ -39,8 +44,7 @@ ;; build process, is ;; xemacs -no-packages -batch \ -;; -eval "(setq generated-autoload-file \"PATH\")" \ -;; -l autoload -f autoload-update-directory-autoloads PREFIX DIRECTORY +;; -l autoload -f batch-update-directory-autoloads PREFIX DIRECTORY ;; which causes XEmacs to update the file named by PATH from the .el ;; files in DIRECTORY (but not recursing into subdirectories) and (if @@ -61,24 +65,13 @@ ;; of XEmacs). ;; The probable next step is to fix up the packages to use the -;; `autoload-update-directory-autoloads' API. However, for backward +;; `batch-update-directory-autoloads' API. However, for backward ;; compatibility with XEmacs 21.4 and 21.1, this can't be done quickly. -;; For now the API used in update-elc-2.el: - -;; (let* ((dir "DIRECTORY") -;; (generated-autoload-file (expand-file-name "auto-autoloads.el" dir)) -;; (autoload-package-name "PREFIX")) -;; (update-autoload-files (list muledir)) -;; (byte-recompile-file generated-autoload-file 0)) - -;; is available, but this ugly kludge is deprecated. It will be removed -;; in favor of using proper arguments instead of special variables. - ;; For backward compatibility the API used in the packages/XEmacs.rules: ;; xemacs -vanilla -batch -eval "$(AUTOLOAD_PACKAGE_NAME)" \ -;; -l autoload -f batch-update-directory $(AUTOLOAD_PATH) +;; -l autoload -f batch-update-autoloads $(AUTOLOAD_PATH) ;; is supported, and the implementation is unchanged. However, ;; revision of the API (in a backward compatible way) and the @@ -130,6 +123,10 @@ ;;; Code: +;; Need to load easy-mmode because we expand macro calls to easy-mmode +;; macros in make-autoloads below. +(require 'easy-mmode) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Standard file and directory names @@ -144,6 +141,10 @@ ;; Dynamic variables for communication among functions +;; FSF 21.2: +;; The autoload file is assumed to contain a trailer starting with a FormFeed +;; character. + (defvar generated-autoload-file (expand-file-name autoload-file-name lisp-directory) "*File `update-file-autoloads' puts autoloads into. @@ -154,6 +155,11 @@ generally the file named by `autoload-file-name' in the directory being updated. XEmacs.rules setq's this variable for package autoloads.") +(defvar generate-autoload-function + #'generate-file-autoloads + "Function to generate the autoloads for a file and insert at point. +Called with one argument, the file.") + (define-obsolete-variable-alias 'autoload-package-name 'autoload-feature-prefix) (defvar autoload-feature-prefix nil @@ -164,6 +170,9 @@ auto-autoloads file). Highest priority candidate except for an explicit argument to `autoload-make-feature-name' (q.v.).") +(defvar autoload-feature-suffix "-autoloads" + "String added to `autoload-feature-prefix' to create the autoload feature name.") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Magic strings in source files @@ -210,40 +219,69 @@ (defconst generate-autoload-section-trailer "\n;;;***\n" "String which indicates the end of the section of autoloads for a file.") +(defconst generate-autoload-section-continuation ";;;;;; " + "String to add on each continuation of the section header form.") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Parsing the source file text. -;; Autoloads in C source differ from those in Lisp source. For historical -;; reasons, functions handling only Lisp don't have "lisp" in their names; -;; maybe this should be changed. +;; Autoloads in C source differ from those in Lisp source. (defun make-autoload (form file) - "Turn a definition generator FORM into an autoload for source file FILE. -Returns nil if FORM is not a defun, defun*, defmacro, defmacro*, -define-skeleton, or define-derived-mode." - (let ((car (car-safe form))) - (if (memq car '(defun defun* define-skeleton defmacro defmacro* - define-derived-mode)) - (let ((macrop (memq car '(defmacro defmacro*))) - name doc) - (setq form (cdr form) - name (car form) - ;; Ignore the arguments. - form (cdr (cond ((eq car 'define-skeleton) - form) - ((eq car 'define-derived-mode) - (cddr form)) - (t - (cdr form)))) - doc (car form)) - (if (stringp doc) - (setq form (cdr form)) - (setq doc nil)) - (list 'autoload (list 'quote name) file doc - (or (eq car 'define-skeleton) - (eq car 'define-derived-mode) - (eq (car-safe (car form)) 'interactive)) - (if macrop (list 'quote 'macro) nil))) - nil))) + "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-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)) + (body (nthcdr (get car 'doc-string-elt) form)) + (doc (if (stringp (car body)) (pop body)))) + ;; `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 a simpler (and less space-consuming) defvar, + ;; but add some extra stuff if it uses :require. + ((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)))))) + (if (not (plist-get rest :require)) + `(defvar ,varname ,init ,doc) + `(progn + (defvar ,varname ,init ,doc) + (custom-add-to-group ,(plist-get rest :group) + ',varname 'custom-variable) + (custom-add-load ',varname + ,(plist-get rest :require)))))) + + ;; nil here indicates that this is not a special autoload form. + (t nil)))) (defun make-c-autoload (module) "Make an autoload list for the DEFUN at point in MODULE. @@ -283,7 +321,7 @@ ;; Generating autoloads for a single file ;;;###autoload -(defun generate-file-autoloads (file &optional funlist) +(defun generate-file-autoloads (file) "Insert at point an autoload section for FILE. autoloads are generated for defuns and defmacros in FILE marked by `generate-autoload-cookie' (which see). @@ -291,26 +329,26 @@ are used." (interactive "fGenerate autoloads for file: ") (cond ((string-match "\\.el$" file) - (generate-autoload-ish-1 + (generate-autoload-type-section file (replace-in-string (file-name-nondirectory file) "\\.elc?$" "") - nil #'generate-file-autoloads-1 - funlist)) + nil #'generate-lisp-file-autoloads-1)) ;; #### jj, are C++ modules possible? ((string-match "\\.c$" file) - (generate-autoload-ish-1 + (generate-autoload-type-section file (replace-in-string (file-name-nondirectory file) "\\.c$" "") - t #'generate-c-file-autoloads-1 - funlist)) + t #'generate-c-file-autoloads-1)) (t (error 'wrong-type-argument file "not a C or Elisp source file")))) -(defun* generate-autoload-ish-1 (file load-name literal fun-to-call &rest args) +(defun* generate-autoload-type-section (file load-name literal fun-to-call) "Insert at point an autoload-type section for FILE. -If LITERAL, open the file literally, without decoding. -Calls FUN-TO-CALL to compute the autoloads, passing it OUTBUF, LOAD-NAME, - TRIM-NAME, and ARGS." +LOAD-NAME is the non-directory portion of the name, with the final .el, .elc +or .c section removed. If LITERAL, open the file literally, without decoding. +Calls FUN-TO-CALL to compute the autoloads, with the loaded file in the +current buffer, passing it OUTBUF (where to write the autoloads), LOAD-NAME, +and TRIM-NAME (result of calling `autoload-trim-file-name' on FILE)." (let ((outbuf (current-buffer)) (trim-name (autoload-trim-file-name file)) (autoloads-done '()) @@ -318,6 +356,7 @@ (print-readably t) ; XEmacs (float-output-format nil) (visited (get-file-buffer file)) + suppress-form ;; (done-any nil) output-end) @@ -329,21 +368,74 @@ ;; subdirectory of the current buffer's directory, we'll make it ;; relative to the current buffer's directory. (setq file (expand-file-name file)) + ;; #### FSF 21.2. Do we want this? +; (let* ((source-truename (file-truename file)) +; (dir-truename (file-name-as-directory +; (file-truename default-directory))) +; (len (length dir-truename))) +; (if (and (< len (length source-truename)) +; (string= dir-truename (substring source-truename 0 len))) +; (setq file (substring source-truename len)))) + + ;; Check for suppression form (XEmacs) + (let* ((dir (file-name-directory file)) + (_pkg (expand-file-name "_pkg.el" dir)) + (pkg-vis (get-file-buffer _pkg)) + pkg-buf) + (save-excursion + (when (file-readable-p _pkg) + (unwind-protect + (progn + (let ((find-file-hooks nil) + (enable-local-variables nil)) + (set-buffer (or pkg-vis (find-file-noselect _pkg))) + (set-syntax-table emacs-lisp-mode-syntax-table)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (block nil + (while (search-forward "(package-suppress" nil t) + ;; skip over package-name + (forward-sexp 1) + (let ((supfile (read (current-buffer)))) + (when (equal supfile load-name) + (setq suppress-form (eval (read (current-buffer)))) + (return)))))))) + (unless pkg-vis + ;; We created this buffer, so we should kill it. + (if pkg-buf (kill-buffer pkg-buf))))))) (save-excursion (unwind-protect (progn - (let ((find-file-hooks nil) - (enable-local-variables nil)) + (let (;(find-file-hooks nil) + ;(enable-local-variables nil) + ) (set-buffer (or visited (find-file-noselect file literal literal ))) ;; This doesn't look right for C files, but it is. The only ;; place we need the syntax table is when snarfing the Lisp ;; function name. (set-syntax-table emacs-lisp-mode-syntax-table)) +; (if visited +; (set-buffer visited) +; ;; It is faster to avoid visiting the file. +; (set-buffer (get-buffer-create " *generate-autoload-file*")) +; (kill-all-local-variables) +; (erase-buffer) +; (setq buffer-undo-list t +; buffer-read-only nil) +; ;; This doesn't look right for C files, but it is. The only +; ;; place we need the syntax table is when snarfing the Lisp +; ;; function name. +; (emacs-lisp-mode) +; (if literal +; (insert-file-contents-literally file nil) +; (insert-file-contents file nil))) (unless (setq autoloads-done - (apply fun-to-call outbuf load-name trim-name args)) - (return-from generate-autoload-ish-1)) + (funcall fun-to-call outbuf load-name trim-name)) + (return-from generate-autoload-type-section)) ) (unless visited ;; We created this buffer, so we should kill it. @@ -354,108 +446,124 @@ ;; XEmacs -- always do this so that we cache the information ;; that we've processed the file already. (progn + ;; 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-done load-name trim-name) + (prin1 (list 'autoloads autoloads-done load-name trim-name + ;; In FSF 21.2. Also in FSF 19.30. Presumably + ;; deleted from XEmacs. + ;; (nth 5 (file-attributes file)) + ) outbuf) (terpri outbuf) - ;;;; (insert ";;; Generated autoloads from " - ;;;; (autoload-trim-file-name file) "\n") - ;; Warn if we put a line in auto-autoloads.el - ;; that is long enough to cause trouble. - (when (< output-end (point)) - (setq output-end (point-marker))) - (while (< (point) output-end) - ;; (let ((beg (point))) - (end-of-line) - ;; Emacs -- I still haven't figured this one out. - ;; (if (> (- (point) beg) 900) - ;; (progn - ;; (message "A line is too long--over 900 characters") - ;; (sleep-for 2) - ;; (goto-char output-end))) - ;; ) - (forward-line 1)) + ;; #### Alas, we will have to think about this. Adding this means + ;; that, once we have created or maintained an auto-autoloads file, + ;; we alone and our successors can update the file. The file itself + ;; will work fine in older XEmacsen, but they won't be able to + ;; update autoloads -- hence, to build. +; ;; 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))))) + ;; XEmacs: This was commented out before. #### Correct? +; (insert ";;; Generated autoloads from " +; (autoload-trim-file-name file) "\n") + ;; XEmacs -- handle suppression + (when suppress-form + (insert "\n;;; Suppress form from _pkg.el\n") + (insert "(unless " (prin1-to-string suppress-form) "\n\n")) (goto-char output-end) + ;; XEmacs -- handle suppression + (when suppress-form + (insert "\n) ;; unless (suppressed)\n")) (insert generate-autoload-section-trailer))) - (or noninteractive ; XEmacs: only need one line in -batch mode. - (message "Generating autoloads for %s...done" file)))) + )) + -(defun* generate-file-autoloads-1 (outbuf load-name trim-name funlist) - "Insert at point an autoload section for FILE. -autoloads are generated for defuns and defmacros in FILE -marked by `generate-autoload-cookie' (which see). -If FILE is being visited in a buffer, the contents of the buffer -are used." +(defun process-one-lisp-autoload (autoloads-done outbuf load-name) + "Process a single autoload at point and write to OUTBUF. +Point should be just after a magic cookie string (e.g. ;;;###autoload). +Updates AUTOLOADS-DONE and returns the new value." + (skip-chars-forward " \t") + ;; (setq done-any t) + (if (eolp) + ;; Read the next form and make an autoload. + (let* ((form (prog1 (read (current-buffer)) + (or (bolp) (forward-line 1)))) + (autoload (make-autoload form load-name))) + (if autoload + (setq autoloads-done (cons (nth 1 form) + autoloads-done)) + (setq autoload form)) + (autoload-print-form autoload outbuf "")) + ;; Copy the rest of the line to the output. + (cond ((looking-at "immediate\\s *$") ; XEmacs + ;; This is here so that you can automatically + ;; have small hook functions copied to + ;; auto-autoloads.el so that it's not necessary + ;; to load a whole file just to get a two-line + ;; do-nothing find-file-hook... --Stig + (forward-line 1) + (let ((begin (point))) + (forward-sexp) + (forward-line 1) + (princ (buffer-substring begin (point)) outbuf))) + (t + (princ (buffer-substring + (progn + ;; Back up over whitespace, to preserve it. + (skip-chars-backward " \f\t") + (if (= (char-after (1+ (point))) ? ) + ;; Eat one space. + (forward-char 1)) + (point)) + (progn (forward-line 1) (point))) + outbuf)))) + autoloads-done) + +(defun* generate-lisp-file-autoloads-1 (outbuf load-name trim-name) + "Insert at point in OUTBUF an autoload section for an Elisp file. +The file is assumed to be already loaded and in the current buffer. +autoloads are generated for defuns and defmacros marked by +`generate-autoload-cookie' (which see)." (let ((autoloads-done '()) - (dofiles (not (null funlist))) ) - (save-excursion (save-restriction (widen) (goto-char (point-min)) (unless (search-forward generate-autoload-cookie nil t) (message "No autoloads found in %s" trim-name) - (return-from generate-file-autoloads-1 nil)) + (return-from generate-lisp-file-autoloads-1 nil)) (message "Generating autoloads for %s..." trim-name) (goto-char (point-min)) - (while (if dofiles funlist (not (eobp))) - (if (not dofiles) - (skip-chars-forward " \t\n\f") - (goto-char (point-min)) - (re-search-forward - (concat "(def\\(un\\|var\\|const\\|macro\\) " - (regexp-quote (symbol-name (car funlist))) - "\\s ")) - (goto-char (match-beginning 0))) + (while (not (eobp)) + (skip-chars-forward " \t\n\f") (cond - ((or dofiles - (looking-at (regexp-quote generate-autoload-cookie))) - (if dofiles - nil - (search-forward generate-autoload-cookie) - (skip-chars-forward " \t")) - ;; (setq done-any t) - (if (or dofiles (eolp)) - ;; Read the next form and make an autoload. - (let* ((form (prog1 (read (current-buffer)) - (or (bolp) (forward-line 1)))) - (autoload (make-autoload form load-name)) - (doc-string-elt (get (car-safe form) - 'doc-string-elt))) - (if autoload - (setq autoloads-done (cons (nth 1 form) - autoloads-done)) - (setq autoload form)) - (print-autoload autoload doc-string-elt outbuf "")) - ;; Copy the rest of the line to the output. - (let ((begin (point))) - ;; (terpri outbuf) - (cond ((looking-at "immediate\\s *$") ; XEmacs - ;; This is here so that you can automatically - ;; have small hook functions copied to - ;; auto-autoloads.el so that it's not necessary - ;; to load a whole file just to get a two-line - ;; do-nothing find-file-hook... --Stig - (forward-line 1) - (setq begin (point)) - (forward-sexp) - (forward-line 1)) - (t - (forward-line 1))) - (princ (buffer-substring begin (point)) outbuf)))) + ((looking-at (regexp-quote generate-autoload-cookie)) + (search-forward generate-autoload-cookie) + (setq autoloads-done + (process-one-lisp-autoload autoloads-done outbuf load-name))) ((looking-at ";") ;; Don't read the comment. (forward-line 1)) (t (forward-sexp 1) (forward-line 1))) - (if dofiles - (setq funlist (cdr funlist)))))) + ))) + (or noninteractive ; XEmacs: only need one line in -batch mode. + (message "Generating autoloads for %s...done" trim-name)) autoloads-done)) -(defun* generate-c-file-autoloads-1 (outbuf load-name trim-name funlist) +(defun* generate-c-file-autoloads-1 (outbuf load-name trim-name + &optional funlist) "Insert at point an autoload section for the C file FILE. autoloads are generated for defuns and defmacros in FILE marked by `generate-c-autoload-cookie' (which see). @@ -488,7 +596,7 @@ (let ((autoload (make-c-autoload load-name))) (when autoload (push (nth 1 (nth 1 autoload)) autoloads-done) - (print-autoload autoload 3 outbuf " ")))) + (autoload-print-form autoload outbuf " ")))) ;; close the princ'd `when' form (princ ")" outbuf)) (goto-char (point-min)) @@ -505,91 +613,175 @@ (let ((autoload (make-c-autoload load-name))) (when autoload (push (nth 1 (nth 1 autoload)) autoloads-done) - (print-autoload autoload 3 outbuf " "))) + (autoload-print-form autoload outbuf " "))) (setq match (search-forward generate-c-autoload-cookie nil t))) ;; close the princ'd `when' form (princ ")" outbuf))))) + (or noninteractive ; XEmacs: only need one line in -batch mode. + (message "Generating autoloads for %s...done" trim-name)) autoloads-done)) -;; Assorted utilities for generating autoloads and pieces thereof +;;;###autoload +(defun generate-custom-defines (file) + "Insert at point a custom-define section for FILE. +If FILE is being visited in a buffer, the contents of the buffer +are used." + (interactive "fGenerate custom defines for file: ") + (cond ((string-match "\\.el$" file) + (generate-autoload-type-section + file + (replace-in-string (file-name-nondirectory file) "\\.elc?$" "") + nil #'generate-custom-defines-1)) + ((string-match "\\.c$" file) + ;; no way to generate custom-defines for C files (currently?), + ;; but cannot signal an error. + nil) + (t + (error 'wrong-type-argument file "not a C or Elisp source file")))) -(defun print-autoload (autoload doc-string-elt outbuf margin) +(defun* generate-custom-defines-1 (outbuf load-name trim-name) + "Insert at point in OUTBUF a custom-define section for an Elisp file. +This contains all defcustoms and defgroups in the file. +The file is assumed to be already loaded and in the current buffer." + (let* ((search-regexp-1 "^(\\(defcustom\\|defgroup\\) ") + (search-string-2 ";;;###custom-define") + (search-regexp-2 (regexp-quote search-string-2)) + (autoloads-done '())) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (unless (or (re-search-forward search-regexp-1 nil t) + (re-search-forward search-regexp-2 nil t)) + (message "No custom defines found in %s" trim-name) + (return-from generate-custom-defines-1 nil)) + (message "Generating custom defines for %s..." trim-name) + (princ "(defconst custom-define-current-source-file " outbuf) + (prin1 (file-relative-name (buffer-file-name) + (symbol-value-in-buffer 'default-directory + outbuf)) outbuf) + (princ ")\n" outbuf) + + (goto-char (point-min)) + (while (not (eobp)) + (skip-chars-forward " \t\n\f") + (cond + ((looking-at search-regexp-1) + ;; Read the next form and copy it to make an autoload. + (let* ((form (prog1 (read (current-buffer)) + (or (bolp) (forward-line 1)))) + (autoload form ;(make-autoload form load-name) + )) + (if autoload + (setq autoloads-done (cons (nth 1 form) + autoloads-done)) + (setq autoload form)) + (autoload-print-form autoload outbuf "")) + ) + ((looking-at search-regexp-2) + (search-forward search-string-2) + (beep) + (setq autoloads-done + (process-one-lisp-autoload autoloads-done outbuf load-name))) + ((looking-at ";") + ;; Don't read the comment. + (forward-line 1)) + (t + (forward-sexp 1) + (forward-line 1))) + ))) + (or noninteractive ; XEmacs: only need one line in -batch mode. + (message "Generating custom defines for %s...done" trim-name)) + autoloads-done)) + +;; Assorted utilities for generating autoloads and pieces thereof + +(defun autoload-print-form (form outbuf margin) "Print an autoload form, handling special characters. In particular, print docstrings with escapes inserted before left parentheses at the beginning of lines and ^L characters." - (if (and doc-string-elt (stringp (nth doc-string-elt autoload))) - ;; 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) autoload)) - (elt (cdr p)) - (start-string (format "\n%s(" margin))) - (setcdr p nil) - (princ start-string outbuf) - ;; XEmacs change: don't let ^^L's get into - ;; the file or sorting is hard. - (let ((print-escape-newlines t) - (p (save-excursion - (set-buffer outbuf) - (point))) + (cond + ;; If the form is a sequence, recurse. + ((eq (car form) 'progn) + (mapcar #'(lambda (x) (autoload-print-form x outbuf margin)) + (cdr form))) + ;; Symbols at the toplevel are meaningless. + ((symbolp form) nil) + (t + (let ((doc-string-elt (get (car-safe form) 'doc-string-elt))) + (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)) + (start-string (format "\n%s(" margin))) + (setcdr p nil) + (princ start-string outbuf) + ;; XEmacs change: don't let ^^L's get into + ;; the file or sorting is hard. + (let ((print-escape-newlines t) + ;;#### FSF 21.2 (print-escape-nonascii t) + (p (point outbuf)) + p2) + (mapcar #'(lambda (elt) + (prin1 elt outbuf) + (princ " " outbuf)) + form) + (with-current-buffer outbuf + (setq p2 (point-marker)) + (goto-char p) + (save-match-data + (while (search-forward "\^L" p2 t) + (delete-char -1) + (insert "\\^L"))) + (goto-char p2))) + (princ "\"\\\n" outbuf) + (let ((begin (point outbuf))) + (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 (search-backward start-string 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) + (princ margin outbuf))) + ;; XEmacs change: another ^L hack + (let ((p (point outbuf)) + (print-escape-newlines t) + ;;#### FSF 21.2 (print-escape-nonascii t) p2) - (mapcar #'(lambda (elt) - (prin1 elt outbuf) - (princ " " outbuf)) - autoload) - (save-excursion - (set-buffer outbuf) + (print form outbuf) + (with-current-buffer outbuf (setq p2 (point-marker)) (goto-char p) (save-match-data (while (search-forward "\^L" p2 t) (delete-char -1) (insert "\\^L"))) - (goto-char p2))) - (princ "\"\\\n" outbuf) - (let ((begin (save-excursion - (set-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. - (save-excursion - (set-buffer outbuf) - (save-excursion - (while (search-backward start-string 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) - (princ margin outbuf))) - ;; XEmacs change: another ^L hack - (let ((p (save-excursion - (set-buffer outbuf) - (point))) - (print-escape-newlines t) - p2) - (print autoload outbuf) - (save-excursion - (set-buffer outbuf) - (setq p2 (point-marker)) - (goto-char p) - (save-match-data - (while (search-forward "\^L" p2 t) - (delete-char -1) - (insert "\\^L"))) - (goto-char p2))))) + (goto-char p2)))))))) ;;; 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. ;;; -;;; defvar and defconst should be also be marked in this way. There is -;;; no interference from make-docfile, which only processes those files -;;; that are loaded into the dumped Emacs, and those files should -;;; never have anything autoloaded here. Problems only occur with files +;;; There used to be the following note here: +;;; ;;; Note: defconst and defvar should NOT be marked in this way. +;;; ;;; We don't want to produce defconsts and defvars that +;;; ;;; make-docfile can grok, because then it would grok them twice, +;;; ;;; once in foo.el (where they are given with ;;;###autoload) and +;;; ;;; once in loaddefs.el. +;;; +;;; Counter-note: Yes, they should be marked in this way. +;;; make-docfile only processes those files that are loaded into the +;;; dumped Emacs, and those files should never have anything +;;; autoloaded here. The above-feared problem only occurs with files ;;; which have autoloaded entries *and* are processed by make-docfile; ;;; there should be no such files. @@ -597,11 +789,18 @@ (put 'defun 'doc-string-elt 3) (put 'defun* 'doc-string-elt 3) (put 'defvar 'doc-string-elt 3) +(put 'defcustom 'doc-string-elt 3) (put 'defconst 'doc-string-elt 3) (put 'defmacro 'doc-string-elt 3) (put 'defmacro* 'doc-string-elt 3) -(put 'define-skeleton 'doc-string-elt 3) +(put 'defsubst 'doc-string-elt 3) +(put 'define-skeleton 'doc-string-elt 2) (put 'define-derived-mode 'doc-string-elt 4) +(put 'easy-mmode-define-minor-mode 'doc-string-elt 2) +(put 'define-minor-mode 'doc-string-elt 2) +(put 'define-generic-mode 'doc-string-elt 7) +;; defin-global-mode has no explicit docstring. +(put 'easy-mmode-define-global-mode 'doc-string-elt 1000) (defun autoload-trim-file-name (file) "Returns relative pathname of FILE including the last directory. @@ -615,6 +814,27 @@ ;; #### is this a good idea? "\\\\" "/")) +(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)))))) + ;;;###autoload (defun update-file-autoloads (file) "Update the autoloads for FILE in `generated-autoload-file' @@ -633,16 +853,42 @@ (trim-name (autoload-trim-file-name file)) section-begin form) (save-excursion + ;; FSF has: [[ We want to get a value for generated-autoload-file + ;; from the local variables section if it's there. ]] Not + ;; applicable in XEmacs, since we always keep the autoloads + ;; up-to-date. + + ;; #### FSF 21.2 adds: [[ We must read/write the file without any + ;; code conversion, but still decode EOLs. ]] Not clear if we need + ;; this. --ben + ;; (let ((coding-system-for-read 'raw-text)) (let ((find-file-hooks nil)) (set-buffer (or (get-file-buffer generated-autoload-file) (find-file-noselect generated-autoload-file)))) + ;; FSF 21.2 says: + + ;; [[ This is to make generated-autoload-file have Unix EOLs, so + ;; that it is portable to all platforms. ]] + ;; (setq buffer-file-coding-system 'raw-text-unix)) + ;; Not applicable in XEmacs, since we always keep the autoloads + ;; up-to-date and recompile when we build. + + ;; FSF 21.2: [not applicable to XEmacs] +; (or (> (buffer-size) 0) +; (error "Autoloads file %s does not exist" buffer-file-name)) +; (or (file-writable-p buffer-file-name) +; (error "Autoloads file %s is not writable" buffer-file-name)) + + ;; NOTE: The rest of this function is totally changed from FSF. + ;; Hence, not synched. + ;; Make sure we can scribble in it. (setq buffer-read-only nil) ;; First delete all sections for this file. (goto-char (point-min)) (while (search-forward generate-autoload-section-header nil t) (setq section-begin (match-beginning 0)) - (setq form (read (current-buffer))) + (setq form (autoload-read-section-header)) (when (string= (nth 2 form) load-name) (search-forward generate-autoload-section-trailer) (delete-region section-begin (point)))) @@ -651,7 +897,7 @@ (block find-insertion-point (goto-char (point-min)) (while (search-forward generate-autoload-section-header nil t) - (setq form (read (current-buffer))) + (setq form (autoload-read-section-header)) (when (string< trim-name (nth 3 form)) ;; Found alphabetically correct insertion point (goto-char (match-beginning 0)) @@ -661,65 +907,15 @@ (goto-char (point-max)))) ; Append. ;; Add in new sections for file - (generate-file-autoloads file)) + (funcall generate-autoload-function file)) (when (interactive-p) (save-buffer))))) -;;;###autoload -(defun update-autoloads-here () - "Update sections of the current buffer generated by `update-file-autoloads'." - (interactive) - (let ((generated-autoload-file (buffer-file-name))) - (save-excursion - (goto-char (point-min)) - (while (search-forward generate-autoload-section-header nil t) - (let* ((form (condition-case () - (read (current-buffer)) - (end-of-file nil))) - (file (nth 3 form))) - ;; XEmacs change: if we can't find the file as specified, look - ;; around a bit more. - (cond ((and (stringp file) - (or (get-file-buffer file) - (file-exists-p file)))) - ((and (stringp file) - (save-match-data - (let ((loc (locate-file (file-name-nondirectory file) - load-path))) - (if (null loc) - nil - (setq loc (expand-file-name - (autoload-trim-file-name loc) - "..")) - (if (or (get-file-buffer loc) - (file-exists-p loc)) - (setq file loc) - nil)))))) - (t - (setq file - (if (y-or-n-p - (format - "Can't find library `%s'; remove its autoloads? " - (nth 2 form) file)) - t - (condition-case () - (read-file-name - (format "Find `%s' load file: " - (nth 2 form)) - nil nil t) - (quit nil)))))) - (if file - (let ((begin (match-beginning 0))) - (search-forward generate-autoload-section-trailer) - (delete-region begin (point)))) - (if (stringp file) - (generate-file-autoloads file))))))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Utilities for batch updates ;;;###autoload -(defun autoload-update-directory-autoloads () +(defun batch-update-directory-autoloads () "Update the autoloads for a directory, using a specified feature prefix. Must be used only with -batch. The feature prefix and directory to update are taken from the first and second elements of `command-line-args-left', @@ -731,15 +927,32 @@ #### The API and semantics of this function are subject to change." (unless noninteractive - (error "autoload-batch-update-autoloads: may be used only with -batch")) - (let* ((autoload-feature-prefix (car command-line-args-left)) - (dir (cadr command-line-args-left)) - (generated-autoload-file (expand-file-name autoload-file-name dir))) - (update-autoload-files (list dir) t t) - (setq command-line-args-left (cddr command-line-args-left)))) + (error "batch-update-directory-autoloads: may be used only with -batch")) + (update-autoload-files (list (cadr command-line-args-left)) + (car command-line-args-left) nil t) + (setq command-line-args-left (cddr command-line-args-left))) ;;;###autoload -(defun update-autoload-files (files-or-dirs &optional all-into-one-file force) +(defun batch-update-directory-custom-defines () + "Update the custom defines for a directory, using a specified feature prefix. +Must be used only with -batch. The feature prefix and directory to update +are taken from the first and second elements of `command-line-args-left', +respectively, and they are then removed from `command-line-args-left'. + +Runs `update-file-autoloads' on each file in the given directory. Always +rewrites the autoloads file, even if unchanged. Makes a feature name by +applying `autoload-make-feature-name' to the specified feature prefix. + +#### The API and semantics of this function are subject to change." + (unless noninteractive + (error "batch-update-directory-custom-defines: may be used only with -batch")) + (update-custom-define-files (list (cadr command-line-args-left)) + (car command-line-args-left) nil t) + (setq command-line-args-left (cddr command-line-args-left))) + +;;;###autoload +(defun update-autoload-files (files-or-dirs feature-prefix + &optional into-file force) "Update all the autoload files associated with FILES-OR-DIRS. FILES-OR-DIRS is a list of files and/or directories to be processed. @@ -747,98 +960,144 @@ each element of FILES-OR-DIRS. Fixup code testing for the autoload file's feature and to provide the feature is added. -If optional ALL-INTO-ONE-FILE is non-`nil', `generated-autoload-file' -should be set to the name of an autoload file and all autoloads will be -placed in that file. `autoload-feature-prefix' should be set to an -appropriate prefix which will be concatenated with \"-autoloads\" to -produce the feature name. Otherwise the appropriate autoload file for -each file or directory (located in that directory, or in the directory of -the specified file) will be updated with the directory's or file's -autoloads and the protective forms will be added, and the files will be -saved. Use of the default here is unreliable, and therefore deprecated. +If optional INTO-FILE is non-`nil', it should specify a file into which +the autoloads will be placed. Otherwise, the autoloads will be placed into +a file named `auto-autoloads.el' in the directory of each element in +FILES-OR-DIRS. + +FEATURE-PREFIX should be set to an appropriate prefix which will +be concatenated with \"-autoloads\" to produce the feature name. Otherwise +the appropriate autoload file for each file or directory (located in that +directory, or in the directory of the specified file) will be updated with +the directory's or file's autoloads and the protective forms will be added, +and the files will be saved. Use of the default here is unreliable, and +therefore deprecated. Note that if some of FILES-OR-DIRS are directories, recursion goes only one level deep. If FORCE is non-nil, always save out the autoload files even if unchanged." + (or (listp files-or-dirs) (setq files-or-dirs (list files-or-dirs))) (let ((defdir (directory-file-name default-directory)) ;; value for all-into-one-file - (autoload-feature-name (autoload-make-feature-name)) - (enable-local-eval nil)) ; Don't query in batch mode. + (autoload-feature-name (autoload-make-feature-name feature-prefix)) + (enable-local-eval nil) ; Don't query in batch mode. + (autoload-feature-prefix feature-prefix) + ;; protect from change + (generated-autoload-file generated-autoload-file)) (dolist (arg files-or-dirs) (setq arg (expand-file-name arg defdir)) (cond ((file-directory-p arg) + (setq generated-autoload-file + (or into-file (expand-file-name autoload-file-name arg))) (message "Updating autoloads for directory %s..." arg) - (update-autoloads-from-directory arg)) + (let ((simple-dir (file-name-as-directory + (file-name-nondirectory + (directory-file-name arg)))) + (enable-local-eval nil)) + (save-excursion + (let ((find-file-hooks nil)) + (set-buffer (find-file-noselect generated-autoload-file))) + (goto-char (point-min)) + (while (search-forward generate-autoload-section-header nil t) + (let* ((begin (match-beginning 0)) + (form (autoload-read-section-header)) + (file (nth 3 form))) + (when (and (stringp file) + (string= (file-name-directory file) simple-dir) + (not (file-exists-p + (expand-file-name + (file-name-nondirectory file) arg)))) + ;; Remove the obsolete section. + (search-forward generate-autoload-section-trailer) + (delete-region begin (point))))) + ;; Update or create autoload sections for existing files. + (mapcar 'update-file-autoloads + (directory-files arg t "^[^=].*\\.\\(el\\|c\\)$"))))) ((file-exists-p arg) + (setq generated-autoload-file + (or into-file (expand-file-name autoload-file-name + (file-name-directory arg)))) (update-file-autoloads arg)) (t (error "No such file or directory: %s" arg))) - (when (not all-into-one-file) + (when (not into-file) (autoload-featurep-protect-autoloads (autoload-make-feature-name - (file-name-nondirectory (directory-file-name arg)))) + (or feature-prefix + (file-name-nondirectory (directory-file-name arg))))) (if force (set-buffer-modified-p t (find-file-noselect generated-autoload-file))))) - (when all-into-one-file + (when into-file (autoload-featurep-protect-autoloads autoload-feature-name) (if force (set-buffer-modified-p - t (find-file-noselect generated-autoload-file)))) + t (find-file-noselect into-file)))) (save-some-buffers t) )) ;;;###autoload -(defun update-autoloads-from-directory (dir) - "Update `generated-autoload-file' with all the current autoloads from DIR. -This runs `update-file-autoloads' on each .el and .c file in DIR. -Obsolete autoload entries for files that no longer exist are deleted. -Note that, if this function is called from `batch-update-directory', -`generated-autoload-file' was rebound in that function. - -You don't really want to be calling this function. Try using -`update-autoload-files' instead." - (interactive "DUpdate autoloads for directory: ") - (setq dir (expand-file-name dir)) - (let ((simple-dir (file-name-as-directory - (file-name-nondirectory - (directory-file-name dir)))) - (enable-local-eval nil)) - (save-excursion - (let ((find-file-hooks nil)) - (set-buffer (find-file-noselect generated-autoload-file))) - (goto-char (point-min)) - (while (search-forward generate-autoload-section-header nil t) - (let* ((begin (match-beginning 0)) - (form (condition-case () - (read (current-buffer)) - (end-of-file nil))) - (file (nth 3 form))) - (when (and (stringp file) - (string= (file-name-directory file) simple-dir) - (not (file-exists-p - (expand-file-name - (file-name-nondirectory file) dir)))) - ;; Remove the obsolete section. - (search-forward generate-autoload-section-trailer) - (delete-region begin (point))))) - ;; Update or create autoload sections for existing files. - (mapcar 'update-file-autoloads - (directory-files dir t "^[^=].*\\.\\(el\\|c\\)$")) - (unless noninteractive - (save-buffer))))) +(defun update-custom-define-files (files-or-dirs feature-prefix + &optional into-file force) + "Update all the custom-define files associated with FILES-OR-DIRS. +Works just like `update-file-autoloads'." + (let* ((autoload-feature-suffix "-custom-defines") + (autoload-file-name "custom-defines.el") + (generate-autoload-function #'generate-custom-defines)) + (update-autoload-files files-or-dirs feature-prefix into-file force))) (defun autoload-featurep-protect-autoloads (sym) (save-excursion (set-buffer (find-file-noselect generated-autoload-file)) (goto-char (point-min)) - (if (and (not (= (point-min) (point-max))) - (not (looking-at ";;; DO NOT MODIFY THIS FILE"))) - (progn - (insert ";;; DO NOT MODIFY THIS FILE\n") - (insert "(if (featurep '" sym ")") - (insert " (error \"Feature " sym " already loaded\"))\n") - (goto-char (point-max)) - (insert "\n(provide '" sym ")\n"))))) + (cond ((eq (point-min) (point-max)) nil) + ;; if there's some junk in the file but no sections, just + ;; delete everything. the junk might be stuff inserted by + ;; an older version of this function. + ((not (search-forward generate-autoload-section-header nil t)) + (delete-region (point-min) (point-max))) + (t + (goto-char (point-min)) + (when (looking-at ";;; DO NOT MODIFY THIS FILE") + (delete-region (point-min) + (progn + (search-forward generate-autoload-section-header) + (match-beginning 0)))) + ;; Determine and set the coding system for the file if under Mule. + ;; If there are any extended characters in the input file, use + ;; `escape-quoted' to make sure that both binary and extended + ;; characters are output properly and distinguished properly. + ;; Otherwise, use `raw-text' for maximum portability with non-Mule + ;; Emacsen. + (if (or (featurep '(not mule)) ;; Don't scan if no Mule support + (progn + (goto-char (point-min)) + ;; mrb- There must be a better way than skip-chars-forward + (skip-chars-forward (concat (char-to-string 0) "-" + (char-to-string 255))) + (eq (point) (point-max)))) + (setq buffer-file-coding-system 'raw-text-unix) + (setq buffer-file-coding-system 'escape-quoted)) + (goto-char (point-min)) + (insert ";;; DO NOT MODIFY THIS FILE") + ;; NOTE: XEmacs prior to 21.5.12 or so had a bug in that it + ;; recognized only one of the two magic-cookie styles (the -*- kind) + ;; in find-file, but both of them in load. We go ahead and put both + ;; in, just to be safe. + (when (eq buffer-file-coding-system 'escape-quoted) + (insert " -*- coding: escape-quoted; -*- +\(or (featurep 'mule) (error \"Loading this file requires Mule support\")) +;;;###coding system: escape-quoted")) + (insert "\n(if (featurep '" sym ")") + (insert " (error \"Feature " sym " already loaded\"))\n") + (goto-char (point-max)) + (save-excursion + (forward-line -1) + (when (looking-at "(provide") + (delete-region (point) (point-max)))) + (unless (bolp) (insert "\n")) + (unless (eq (char-before (1- (point))) ?\^L) + (insert "\^L\n")) + (insert "(provide '" sym ")\n"))))) (defun autoload-make-feature-name (&optional prefix) "Generate the feature name to protect this auto-autoloads file from PREFIX. @@ -864,19 +1123,23 @@ (file-name-directory generated-autoload-file)))) (t (error 'invalid-argument "Could not compute a feature name"))) - "-autoloads")) + autoload-feature-suffix)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Deprecated entry points ;; A grep of the core and packages shows use of `batch-update-autoloads' ;; by XEmacs.rules, pcomplete, eshell, oort-gnus; `batch-update-directory' -;; by liece. +;; by liece. The other two entry points (`batch-update-one-directory', +;; `batch-force-update-one-directory') were not used at all. +;; +;; All except the first are now history. liece has been updated. +;; XEmacs.rules has been updated. The others will be, eventually. -;; #### these entry points below are a big mess, especially the -;; first two. there don't seem to be very many packages that use the -;; first one (the "all-into-one-file" variety), and do they actually -;; rely on this functionality? --ben +;; There don't seem to be very many packages that use the first one (the +;; "all-into-one-file" variety), and do they actually rely on this +;; functionality? --ben + ;; but XEmacs.rules does, though maybe it doesn't "rely" on it, and ;; modules do now, and that relies on it. --sjt @@ -891,59 +1154,15 @@ on the command line." (unless noninteractive (error "batch-update-autoloads is to be used only with -batch")) - (update-autoload-files command-line-args-left t) + (update-autoload-files command-line-args-left generated-autoload-file) (kill-emacs 0)) -;;;###autoload -(defun batch-update-directory () - "Update the autoloads for the directories on the command line. -Runs `update-file-autoloads' on each file in the given directory, and must -be used only with -batch. - -Uses and removes the first element of `command-line-args-left'." - (unless noninteractive - (error "batch-update-directory is to be used only with -batch")) - (update-autoload-files command-line-args-left) - ;; (kill-emacs 0) - (setq command-line-args-left nil)) - -;;;###autoload -(defun batch-update-one-directory () - "Update the autoloads for a single directory on the command line. -Runs `update-file-autoloads' on each file in the given directory, and must -be used only with -batch." - (unless noninteractive - (error "batch-update-one-directory is to be used only with -batch")) - (let ((arg (car command-line-args-left))) - (setq command-line-args-left (cdr command-line-args-left)) - (update-autoload-files (list arg)))) - -;;;###autoload -(defun batch-force-update-one-directory () - "Update the autoloads for a single directory on the command line. -Runs `update-file-autoloads' on each file in the given directory, and must -be used only with -batch. Always rewrites the autoloads file, even if -unchanged. - -Uses and removes the first element of `command-line-args-left'." - (unless noninteractive - (error "batch-force-update-directory is to be used only with -batch")) - (let ((arg (car command-line-args-left))) - (setq command-line-args-left (cdr command-line-args-left)) - (update-autoload-files (list arg) nil t))) - ;; Declare obsolescence (make-obsolete-variable 'autoload-target-directory "Don't use this. Bind `generated-autoload-file' to an absolute path.") (make-obsolete 'batch-update-autoloads 'autoload-update-directory-autoloads) -(make-obsolete 'batch-update-directory - 'autoload-update-directory-autoloads) -(make-obsolete 'batch-update-one-directory - 'autoload-update-directory-autoloads) -(make-obsolete 'batch-force-update-one-directory - 'autoload-update-directory-autoloads) (provide 'autoload) diff -r a9527fcdf77f -r c4c8a36043be lisp/easy-mmode.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/easy-mmode.el Thu Feb 03 07:11:28 2005 +0000 @@ -0,0 +1,601 @@ +;;; easy-mmode.el --- easy definition for major and minor modes + +;; Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc. + +;; Author: Georges Brun-Cottan +;; Maintainer: Stefan Monnier + +;; Keywords: extensions lisp + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: GNU Emacs 21.3. + +;;; Commentary: + +;; Minor modes are useful and common. This package makes defining a +;; minor mode easy, by focusing on the writing of the minor mode +;; functionalities themselves. Moreover, this package enforces a +;; conventional naming of user interface primitives, making things +;; natural for the minor-mode end-users. + +;; For each mode, easy-mmode defines the following: +;; : The minor mode predicate. A buffer-local variable. +;; -map : The keymap possibly associated to . +;; -hook,-on-hook,-off-hook and -mode: +;; see `define-minor-mode' documentation +;; +;; eval +;; (pp (macroexpand '(define-minor-mode ))) +;; to check the result before using it. + +;; The order in which minor modes are installed is important. Keymap +;; lookup proceeds down minor-mode-map-alist, and the order there +;; tends to be the reverse of the order in which the modes were +;; installed. Perhaps there should be a feature to let you specify +;; orderings. + +;; Additionally to `define-minor-mode', the package provides convenient +;; ways to define keymaps, and other helper functions for major and minor +;; modes. + +;;; Code: + +(eval-when-compile (require 'cl)) + +;;; This file uses two functions that did not exist in some versions of +;;; XEmacs: propertize and replace-regexp-in-string. We provide these +;;; functions here for such XEmacsen. +;;; +;;; FIXME: These function definitions should go into the future or +;;; forward-compat package, once that package exists. + +;; XEmacs <= 21.4 does not have propertize, but XEmacs >= 21.5 dumps it (it is +;; defined in subr.el). Therefore, it is either defined regardless of what +;; has been loaded already, or it won't be defined regardless of what is +;; loaded. +(if (not (fboundp 'propertize)) + (defun propertize (string &rest properties) + "Return a copy of STRING with text properties added. +First argument is the string to copy. +Remaining arguments form a sequence of PROPERTY VALUE pairs for text +properties to add to the result." + (let ((str (copy-sequence string))) + (add-text-properties 0 (length str) + properties + str) + str))) + +;; XEmacs <= 21.4 does not have replace-regexp-in-string, but XEmacs >= 21.5 +;; dumps it (it is defined in subr.el). Therefore, it is either defined +;; regardless of what has been loaded already, or it won't be defined +;; regardless of what is loaded. +(if (not (fboundp 'replace-regexp-in-string)) + (defun replace-regexp-in-string (regexp rep string &optional + fixedcase literal subexp start) + "Replace all matches for REGEXP with REP in STRING. + +Return a new string containing the replacements. + +Optional arguments FIXEDCASE, LITERAL and SUBEXP are like the +arguments with the same names of function `replace-match'. If START +is non-nil, start replacements at that index in STRING. + +REP is either a string used as the NEWTEXT arg of `replace-match' or a +function. If it is a function it is applied to each match to generate +the replacement passed to `replace-match'; the match-data at this +point are such that match 0 is the function's argument. + +To replace only the first match (if any), make REGEXP match up to \\' +and replace a sub-expression, e.g. + (replace-regexp-in-string \"\\(foo\\).*\\'\" \"bar\" \" foo foo\" nil nil 1) + => \" bar foo\" +" + (let ((l (length string)) + (start (or start 0)) + matches str mb me) + (save-match-data + (while (and (< start l) (string-match regexp string start)) + (setq mb (match-beginning 0) + me (match-end 0)) + ;; If we matched the empty string, make sure we advance by one char + (when (= me mb) (setq me (min l (1+ mb)))) + ;; Generate a replacement for the matched substring. + ;; Operate only on the substring to minimize string consing. + ;; Set up match data for the substring for replacement; + ;; presumably this is likely to be faster than munging the + ;; match data directly in Lisp. + (string-match regexp (setq str (substring string mb me))) + (setq matches + (cons (replace-match (if (stringp rep) + rep + (funcall rep (match-string 0 str))) + fixedcase literal str subexp) + (cons (substring string start mb) ; unmatched prefix + matches))) + (setq start me)) + ;; Reconstruct a string from the pieces. + (setq matches (cons (substring string start l) matches)) ; leftover + (apply #'concat (nreverse matches)))))) + + +(defun easy-mmode-pretty-mode-name (mode &optional lighter) + "Turn the symbol MODE into a string intended for the user. +If provided LIGHTER will be used to help choose capitalization." + (let* ((case-fold-search t) + (name (concat (replace-regexp-in-string + "-Minor" " minor" + (capitalize (replace-regexp-in-string + "-mode\\'" "" (symbol-name mode)))) + " mode"))) + (if (not (stringp lighter)) name + (setq lighter + (replace-regexp-in-string "\\`\\s-+\\|\\-s+\\'" "" lighter)) + (replace-regexp-in-string lighter lighter name t t)))) + +;; XEmacs change: add -on-hook, -off-hook, and macro parameter documentation. +;;;###no-autoload +(defalias 'easy-mmode-define-minor-mode 'define-minor-mode) +;;;###no-autoload +(defmacro define-minor-mode (mode doc &optional init-value lighter keymap &rest body) + "Define a new minor mode MODE. +This function defines the associated control variable MODE, keymap MODE-map, +toggle command MODE, and hook MODE-hook. + +DOC is the documentation for the mode toggle command. +Optional INIT-VALUE is the initial value of the mode's variable. +Optional LIGHTER is displayed in the modeline when the mode is on. +Optional KEYMAP is the default (defvar) keymap bound to the mode keymap. + If it is a list, it is passed to `easy-mmode-define-keymap' + in order to build a valid keymap. It's generally better to use + a separate MODE-map variable than to use this argument. +The above three arguments can be skipped if keyword arguments are +used (see below). + +BODY contains code that will be executed each time the mode is (de)activated. + It will be executed after any toggling but before running the hooks. + Before the actual body code, you can write + keyword arguments (alternating keywords and values). + These following keyword arguments are supported: +:group GROUP Custom group name to use in all generated `defcustom' forms. +:global GLOBAL If non-nil specifies that the minor mode is not meant to be + buffer-local, so don't make the variable MODE buffer-local. + By default, the mode is buffer-local. +:init-value VAL Same as the INIT-VALUE argument. +:lighter SPEC Same as the LIGHTER argument. +:require SYM Same as in `defcustom'. + +For backwards compatibility, these hooks are run each time the mode is +\(de)activated. When the mode is toggled, MODE-hook is always run before the +other hook. +MODE-hook: run if the mode is toggled. +MODE-on-hook: run if the mode is activated. +MODE-off-hook: run if the mode is deactivated. + +\(defmacro easy-mmode-define-minor-mode + (MODE DOC &optional INIT-VALUE LIGHTER KEYMAP &rest BODY)...\) + +For example, you could write + (define-minor-mode foo-mode \"If enabled, foo on you!\" + nil \"Foo \" foo-keymap + :require 'foo :global t :group 'inconvenience + ...BODY CODE...)" + + ;; Allow skipping the first three args. + (cond + ((keywordp init-value) + (setq body (list* init-value lighter keymap body) + init-value nil lighter nil keymap nil)) + ((keywordp lighter) + (setq body (list* lighter keymap body) lighter nil keymap nil)) + ((keywordp keymap) (push keymap body) (setq keymap nil))) + + (let* ((mode-name (symbol-name mode)) + (pretty-name (easy-mmode-pretty-mode-name mode lighter)) + (globalp nil) + (group nil) + (extra-args nil) + (require t) + (keymap-sym (if (and keymap (symbolp keymap)) keymap + (intern (concat mode-name "-map")))) + (hook (intern (concat mode-name "-hook"))) + (hook-on (intern (concat mode-name "-on-hook"))) + (hook-off (intern (concat mode-name "-off-hook")))) + + ;; Check keys. + (while (keywordp (car body)) + (case (pop body) + (:init-value (setq init-value (pop body))) + (:lighter (setq lighter (pop body))) + (:global (setq globalp (pop body))) + (:extra-args (setq extra-args (pop body))) + (:group (setq group (nconc group (list :group (pop body))))) + (:require (setq require (pop body))) + (t (pop body)))) + + (unless group + ;; We might as well provide a best-guess default group. + (setq group + `(:group ',(or (custom-current-group) + (intern (replace-regexp-in-string + "-mode\\'" "" mode-name)))))) + ;; Add default properties to LIGHTER. +;; #### FSF comments this out in 21.3. +; (unless (or (not (stringp lighter)) +; (get-text-property 0 'local-map lighter) +; (get-text-property 0 'keymap lighter)) +; (setq lighter +; (propertize lighter +; 'local-map modeline-minor-mode-map ; XEmacs change +; 'help-echo "mouse-3: minor mode menu"))) + + `(progn + ;; Define the variable to enable or disable the mode. + ,(if (not globalp) + `(progn + (defvar ,mode ,init-value ,(format "Non-nil if %s is enabled. +Use the command `%s' to change this variable." pretty-name mode)) + (make-variable-buffer-local ',mode)) + + (let ((curfile (or (and (boundp 'byte-compile-current-file) + byte-compile-current-file) + load-file-name))) + `(defcustom ,mode ,init-value + ,(format "Non-nil if %s is enabled. +See the command `%s' for a description of this minor-mode. +Setting this variable directly does not take effect; +use either \\[customize] or the function `%s'." + pretty-name mode mode) + :set (lambda (symbol value) (funcall symbol (or value 0))) + :initialize 'custom-initialize-default + ,@group + :type 'boolean + ,@(cond + ((not (and curfile require)) nil) + ((not (eq require t)) `(:require ,require)) + (t `(:require + ',(intern (file-name-nondirectory + (file-name-sans-extension curfile))))))))) + + ;; The actual function. + (defun ,mode (&optional arg ,@extra-args) + ,(or doc + (format (concat "Toggle %s on or off. +Interactively, with no prefix argument, toggle the mode. +With universal prefix ARG turn mode on. +With zero or negative ARG turn mode off. +\\{%s}") pretty-name keymap-sym)) + ;; Use `toggle' rather than (if ,mode 0 1) so that using + ;; repeat-command still does the toggling correctly. + (interactive (list (or current-prefix-arg 'toggle))) + ;; XEmacs addition: save the old mode + (let ((old-mode ,mode)) + (setq ,mode + (cond + ((eq arg 'toggle) (not ,mode)) + (arg (or (listp arg);; XEmacs addition: C-u alone + (> (prefix-numeric-value arg) 0))) + (t + (if (null ,mode) t + (message + "Toggling %s off; better pass an explicit argument." + ',mode) + nil)))) + ,@body + ;; The on/off hooks are here for backward compatibility only. + ;; The on/off hooks are here for backward compatibility only. + ;; XEmacs change: check mode before running hooks + (and ,hook + (not (equal old-mode ,mode)) + (run-hooks ',hook)) + (and ,hook-on + ,mode + (run-hooks ',hook-on)) + (and ,hook-off + (not ,mode) + (run-hooks ',hook-off))) + (if (interactive-p) + (progn + ,(if globalp `(customize-mark-as-set ',mode)) + (message ,(format "%s %%sabled" pretty-name) + (if ,mode "en" "dis")))) + (force-mode-line-update) + ;; Return the new setting. + ,mode) + + ;; Autoloading an easy-mmode-define-minor-mode autoloads + ;; everything up-to-here. + ;; + ;; XEmacs change: XEmacs does not support :autoload-end. On the other + ;; hand, I don't see why we need to support it. An autoload cookie + ;; just before a (define-minor-mode foo) form will generate an autoload + ;; form for the file with name foo. But that's exactly right, since + ;; the defun created just above here has the name foo. There are no + ;; other top-level forms created above here by the macro, so we're done. + ;; + ;;:autoload-end + + ;; The toggle's hook. + (defcustom ,hook nil + ,(format "Hook run at the end of function `%s'." mode-name) + ,@group + :type 'hook) + + ;; XEmacs addition: declare the on and off hooks also + (defcustom ,hook-on nil + ,(format "Hook to run when entering %s." mode-name) + :group ,(cadr group) + :type 'hook) + + (defcustom ,hook-off nil + ,(format "Hook to run when exiting %s." mode-name) + :group ,(cadr group) + :type 'hook) + + ;; Define the minor-mode keymap. + ,(unless (symbolp keymap) ;nil is also a symbol. + `(defvar ,keymap-sym + (let ((m ,keymap)) + (cond ((keymapp m) m) + ((listp m) (easy-mmode-define-keymap m)) + (t (error "Invalid keymap %S" ,keymap)))) + ,(format "Keymap for `%s'." mode-name))) + + (add-minor-mode ',mode ',lighter + ,(if keymap keymap-sym + `(if (boundp ',keymap-sym) + (symbol-value ',keymap-sym))) + ;; XEmacs change: supply the AFTER and TOGGLE-FUN args + t ',mode) + + ;; If the mode is global, call the function according to the default. + ,(if globalp + `(if (and load-file-name (not (equal ,init-value ,mode)) + ;; XEmacs addition: + (not purify-flag)) + (eval-after-load load-file-name '(,mode (if ,mode 1 -1)))))))) + +;;; +;;; make global minor mode +;;; + +;;;###no-autoload +(defmacro easy-mmode-define-global-mode (global-mode mode turn-on + &rest keys) + "Make GLOBAL-MODE out of the buffer-local minor MODE. +TURN-ON is a function that will be called with no args in every buffer + and that should try to turn MODE on if applicable for that buffer. +KEYS is a list of CL-style keyword arguments: +:group to specify the custom group." + (let* ((global-mode-name (symbol-name global-mode)) + (pretty-name (easy-mmode-pretty-mode-name mode)) + (pretty-global-name (easy-mmode-pretty-mode-name global-mode)) + (group nil) + (extra-args nil) + (buffers (intern (concat global-mode-name "-buffers"))) + (cmmh (intern (concat global-mode-name "-cmmh")))) + + ;; Check keys. + (while (keywordp (car keys)) + (case (pop keys) + (:extra-args (setq extra-args (pop keys))) + (:group (setq group (nconc group (list :group (pop keys))))) + (t (setq keys (cdr keys))))) + + (unless group + ;; We might as well provide a best-guess default group. + (setq group + `(:group ',(or (custom-current-group) + (intern (replace-regexp-in-string + "-mode\\'" "" (symbol-name mode))))))) + + `(progn + ;; The actual global minor-mode + (define-minor-mode ,global-mode + ,(format "Toggle %s in every buffer. +With prefix ARG, turn %s on if and only if ARG is positive. +%s is actually not turned on in every buffer but only in those +in which `%s' turns it on." + pretty-name pretty-global-name pretty-name turn-on) + :global t :extra-args ,extra-args ,@group + + ;; Setup hook to handle future mode changes and new buffers. + (if ,global-mode + ;; XEmacs: find-file-hooks not find-file-hook + (progn + (add-hook 'find-file-hooks ',buffers) + (add-hook 'change-major-mode-hook ',cmmh)) + (remove-hook 'find-file-hooks ',buffers) + (remove-hook 'change-major-mode-hook ',cmmh)) + + ;; Go through existing buffers. + (dolist (buf (buffer-list)) + (with-current-buffer buf + (if ,global-mode (,turn-on) (when ,mode (,mode -1)))))) + + ;; TODO: XEmacs does not support :autoload-end + ;; Autoloading easy-mmode-define-global-mode + ;; autoloads everything up-to-here. + :autoload-end + + ;; List of buffers left to process. + (defvar ,buffers nil) + + ;; The function that calls TURN-ON in each buffer. + (defun ,buffers () + (remove-hook 'post-command-hook ',buffers) + (while ,buffers + (let ((buf (pop ,buffers))) + (when (buffer-live-p buf) + (with-current-buffer buf (,turn-on)))))) + (put ',buffers 'definition-name ',global-mode) + + ;; The function that catches kill-all-local-variables. + (defun ,cmmh () + (add-to-list ',buffers (current-buffer)) + (add-hook 'post-command-hook ',buffers)) + (put ',cmmh 'definition-name ',global-mode)))) + +;;; +;;; easy-mmode-defmap +;;; + +(if (fboundp 'set-keymap-parents) + (defalias 'easy-mmode-set-keymap-parents 'set-keymap-parents) + (defun easy-mmode-set-keymap-parents (m parents) + (set-keymap-parent + m + (cond + ((not (consp parents)) parents) + ((not (cdr parents)) (car parents)) + (t (let ((m (copy-keymap (pop parents)))) + (easy-mmode-set-keymap-parents m parents) + m)))))) + +;;;###no-autoload +(defun easy-mmode-define-keymap (bs &optional name m args) + "Return a keymap built from bindings BS. +BS must be a list of (KEY . BINDING) where +KEY and BINDINGS are suitable for `define-key'. +Optional NAME is passed to `make-sparse-keymap'. +Optional map M can be used to modify an existing map. +ARGS is a list of additional keyword arguments." + (let (inherit dense ;suppress + ) + (while args + (let ((key (pop args)) + (val (pop args))) + (case key + (:name (setq name val)) + (:dense (setq dense val)) + (:inherit (setq inherit val)) + (:group) + ;;((eq key :suppress) (setq suppress val)) + (t (message "Unknown argument %s in defmap" key))))) + (unless (keymapp m) + (setq bs (append m bs)) + (setq m (if dense (make-keymap name) (make-sparse-keymap name)))) + (dolist (b bs) + (let ((keys (car b)) + (binding (cdr b))) + (dolist (key (if (consp keys) keys (list keys))) + (cond + ((symbolp key) + (substitute-key-definition key binding m global-map)) + ((null binding) + (unless (keymapp (lookup-key m key)) (define-key m key binding))) + ((let ((o (lookup-key m key))) + (or (null o) (numberp o) (eq o 'undefined))) + (define-key m key binding)))))) + (cond + ((keymapp inherit) (set-keymap-parent m inherit)) + ((consp inherit) (easy-mmode-set-keymap-parents m inherit))) + m)) + +;;;###no-autoload +(defmacro easy-mmode-defmap (m bs doc &rest args) + `(defconst ,m + (easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args)) + ,doc)) + + +;;; +;;; easy-mmode-defsyntax +;;; + +(defun easy-mmode-define-syntax (css args) + (let ((st (make-syntax-table (plist-get args :copy))) + (parent (plist-get args :inherit))) + (dolist (cs css) + (let ((char (car cs)) + (syntax (cdr cs))) + (if (sequencep char) + (mapcar (lambda (c) (modify-syntax-entry c syntax st)) char) + (modify-syntax-entry char syntax st)))) + ;; XEmacs change: we do not have set-char-table-parent + (if parent (derived-mode-merge-syntax-tables + (if (symbolp parent) (symbol-value parent) parent) st)) + st)) + +;;;###no-autoload +(defmacro easy-mmode-defsyntax (st css doc &rest args) + "Define variable ST as a syntax-table. +CSS contains a list of syntax specifications of the form (CHAR . SYNTAX)." + `(progn + (autoload 'easy-mmode-define-syntax "easy-mmode") + (defconst ,st (easy-mmode-define-syntax ,css ,(cons 'list args)) ,doc))) + + + +;;; +;;; easy-mmode-define-navigation +;;; + +;; XEmacs change: autoload +;;;###no-autoload +(defmacro easy-mmode-define-navigation (base re &optional name endfun) + "Define BASE-next and BASE-prev to navigate in the buffer. +RE determines the places the commands should move point to. +NAME should describe the entities matched by RE. It is used to build + the docstrings of the two functions. +BASE-next also tries to make sure that the whole entry is visible by + searching for its end (by calling ENDFUN if provided or by looking for + the next entry) and recentering if necessary. +ENDFUN should return the end position (with or without moving point)." + (let* ((base-name (symbol-name base)) + (prev-sym (intern (concat base-name "-prev"))) + (next-sym (intern (concat base-name "-next")))) + (unless name (setq name (symbol-name base-name))) + `(progn + (add-to-list 'debug-ignored-errors + ,(concat "^No \\(previous\\|next\\) " (regexp-quote name))) + (defun ,next-sym (&optional count) + ,(format "Go to the next COUNT'th %s." name) + (interactive) + (unless count (setq count 1)) + (if (< count 0) (,prev-sym (- count)) + (if (looking-at ,re) (incf count)) + (if (not (re-search-forward ,re nil t count)) + (if (looking-at ,re) + (goto-char (or ,(if endfun `(,endfun)) (point-max))) + (error ,(format "No next %s" name))) + (goto-char (match-beginning 0)) + (when (and (eq (current-buffer) (window-buffer (selected-window))) + (interactive-p)) + (let ((endpt (or (save-excursion + ,(if endfun `(,endfun) + `(re-search-forward ,re nil t 2))) + (point-max)))) + ;; XEmacs change: versions < 21.5.16 have a + ;; pos-visible-in-window-p that takes only 2 parameters + (unless + (if (eq (function-max-args #'pos-visible-in-window-p) 2) + (pos-visible-in-window-p endpt nil) + (pos-visible-in-window-p endpt nil t)) + (recenter '(0)))))))) + (defun ,prev-sym (&optional count) + ,(format "Go to the previous COUNT'th %s" (or name base-name)) + (interactive) + (unless count (setq count 1)) + (if (< count 0) (,next-sym (- count)) + (unless (re-search-backward ,re nil t count) + (error ,(format "No previous %s" name)))))))) + +(provide 'easy-mmode) + +;;; easy-mmode.el ends here diff -r a9527fcdf77f -r c4c8a36043be lisp/regexp-opt.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/regexp-opt.el Thu Feb 03 07:11:28 2005 +0000 @@ -0,0 +1,278 @@ +;;; regexp-opt.el --- generate efficient regexps to match strings + +;; Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc. + +;; Author: Simon Marshall +;; Maintainer: FSF +;; Keywords: strings, regexps, extensions + +;; Modified by Karl M. Hegbloom Sep. 1997 to support the new regexp syntax +;; with shy groups. (benchmarks pending) + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; The "opt" in "regexp-opt" stands for "optim\\(al\\|i\\(se\\|ze\\)\\)". +;; +;; This package generates a regexp from a given list of strings (which matches +;; one of those strings) so that the regexp generated by: +;; +;; (regexp-opt strings) +;; +;; is equivalent to, but more efficient than, the regexp generated by: +;; +;; (mapconcat 'regexp-quote strings "\\|") +;; +;; For example: +;; +;; (let ((strings '("cond" "if" "when" "unless" "while" +;; "let" "let*" "progn" "prog1" "prog2" +;; "save-restriction" "save-excursion" "save-window-excursion" +;; "save-current-buffer" "save-match-data" +;; "catch" "throw" "unwind-protect" "condition-case"))) +;; (concat "(" (regexp-opt strings t) "\\>")) +;; +;; => "(\\(?:c\\(?:atch\\|ond\\(?:ition-case\\)?\\)\\|if\\|let\\*?\\|prog[12n]\\|save-\\(?:current-buffer\\|excursion\\|match-data\\|restriction\\|window-excursion\\)\\|throw\\|un\\(?:less\\|wind-protect\\)\\|wh\\(?:en\\|ile\\)\\)\\>" +;; +;; +;; (let ((strings '("cond" "if" "when" "unless" "while" +;; "let" "let*" "progn" "prog1" "prog2" +;; "save-restriction" "save-excursion" "save-window-excursion" +;; "save-current-buffer" "save-match-data" +;; "catch" "throw" "unwind-protect" "condition-case"))) +;; (concat "(" (regexp-opt strings t t) "\\>")) +;; ^ +;; => "(\\(c\\(atch\\|ond\\(ition-case\\)?\\)\\|if\\|let\\*?\\|prog[12n]\\|save-\\(current-buffer\\|excursion\\|match-data\\|restriction\\|window-excursion\\)\\|throw\\|un\\(less\\|wind-protect\\)\\|wh\\(en\\|ile\\)\\)\\>" +;; +;; +;; Searching using the above example `regexp-opt' regexp takes approximately +;; two-thirds of the time taken using the equivalent `mapconcat' regexp. + +;; Since this package was written to produce efficient regexps, not regexps +;; efficiently, it is probably not a good idea to in-line too many calls in +;; your code, unless you use the following trick with `eval-when-compile': +;; +;; (defvar definition-regexp +;; (eval-when-compile +;; (concat "^(" +;; (regexp-opt '("defun" "defsubst" "defmacro" "defalias" +;; "defvar" "defconst") t) +;; "\\>"))) +;; +;; The `byte-compile' code will be as if you had defined the variable thus: +;; +;; (defvar definition-regexp +;; "^(\\(def\\(alias\\|const\\|macro\\|subst\\|un\\|var\\)\\)\\>") +;; +;; Note that if you use this trick for all instances of `regexp-opt' and +;; `regexp-opt-depth' in your code, regexp-opt.el would only have to be loaded +;; at compile time. But note also that using this trick means that should +;; regexp-opt.el be changed, perhaps to fix a bug or to add a feature to +;; improve the efficiency of `regexp-opt' regexps, you would have to recompile +;; your code for such changes to have effect in your code. + +;; Originally written for font-lock.el, from an idea from Stig's hl319.el, with +;; thanks for ideas also to Michael Ernst, Bob Glickstein and Dan Nicolaescu. +;; Please don't tell me that it doesn't produce optimal regexps; I know that +;; already. For example, the above explanation for the meaning of "opt" would +;; be more efficient as "optim\\(al\\|i[sz]e\\)", but this requires complex +;; forward looking. But (ideas or) code to improve things (are) is welcome. + +;;; Code: + +;;;###autoload +(defun regexp-opt (strings &optional paren non-shy) + "Return a regexp to match a string in STRINGS. +Each string should be unique in STRINGS and should not contain any regexps, +quoted or not. If optional PAREN is non-nil, ensure that the returned regexp +is enclosed by at least one regexp match grouping construct. If optional +NON-SHY is non nil, the inner groupings will use \"\\\\( \\\\)\" grouping, +rather than the default \"\\\\(?: \\\\)\" 'shy', or non-match-capturing groups. +The returned regexp is typically more efficient than the equivalent regexp: + + (let ((open-paren (if PAREN \"\\\\(\" \"\")) (close-paren (if PAREN \"\\\\)\" \"\"))) + (concat open-paren (mapconcat 'regexp-quote STRINGS \"\\\\|\") close-paren)) + +but typically contains more regexp grouping constructs. +Use `regexp-opt-depth' to count them. + +If PAREN is `words', then the resulting regexp is additionally surrounded +by \\=\\< and \\>." + (save-match-data + ;; Recurse on the sorted list. + (let* ((max-lisp-eval-depth (* 1024 1024)) + (completion-ignore-case nil) + (words (eq paren 'words)) + (sorted-strings (sort (copy-sequence strings) 'string-lessp)) + (re (regexp-opt-group sorted-strings paren nil non-shy))) + (if words (concat "\\<" re "\\>") re)))) + +;;;###autoload +(defun regexp-opt-depth (regexp &optional count-shy-groups-too) + "Return the depth of REGEXP. +This means the number of regexp grouping constructs (parenthesised +expressions) in REGEXP, not counting the \"\\\\(?: \\\\)\" +non-match-capturing groups unless COUNT-SHY-GROUPS-TOO is non-nil. +See `regexp-opt'." + (save-match-data + ;; Hack to signal an error if REGEXP does not have balanced parentheses. + (string-match regexp "") + ;; Count the number of open parentheses in REGEXP. + (let ((max (1- (length regexp))) + (count 0) start) + (while (string-match "\\\\(" regexp start) + (setq start (match-end 0)) + (when (or count-shy-groups-too + (not (string= (substring regexp start (min (+ start 2) max)) "?:"))) + (setq count (1+ count)))) + count))) + +;;; Workhorse functions. + +(eval-when-compile + (require 'cl)) + +(unless (fboundp 'make-bool-vector) + (defalias 'make-bool-vector 'make-vector)) + +(defun regexp-opt-group (strings &optional paren lax non-shy) + "Return a regexp to match a string in STRINGS. +If PAREN non-nil, output regexp parentheses around returned regexp. +If LAX non-nil, don't output parentheses if it doesn't require them. +If NON-SHY non-nil, don't use \\(?: \\) shy groups, use match capturing ones. +Merges keywords to avoid backtracking in Emacs' regexp matcher. + +The basic idea is to find the shortest common prefix, remove it +and recurse. If there is no prefix, we divide the list into two so that +\(at least) one half will have at least a one-character common prefix. + +Also we delay the addition of grouping parenthesis as long as possible +until we're sure we need them, and try to remove one-character sequences +so we can use character sets rather than grouping parenthesis." + (let* ((open-group (cond + ((and paren non-shy) "\\(") + (paren "\\(?:") + (t ""))) + (close-group (if paren "\\)" "")) + (open-charset (if lax "" open-group)) + (close-charset (if lax "" close-group))) + (cond + ;; + ;; If there are no strings, just return the empty string. + ((= (length strings) 0) + "") + ;; + ;; If there is only one string, just return it. + ((= (length strings) 1) + (if (= (length (car strings)) 1) + (concat open-charset (regexp-quote (car strings)) close-charset) + (concat open-group (regexp-quote (car strings)) close-group))) + ;; + ;; If there is an empty string, remove it and recurse on the rest. + ((= (length (car strings)) 0) + (concat open-charset + (regexp-opt-group (cdr strings) t t non-shy) "?" + close-charset)) + ;; + ;; If all are one-character strings, just return a character set. + ((= (length strings) (apply '+ (mapcar 'length strings))) + (concat open-charset + (regexp-opt-charset strings) + close-charset)) + ;; + ;; We have a list of different length strings. + (t + (let ((prefix (try-completion "" (mapcar 'list strings))) + (letters (let ((completion-regexp-list '("^.$"))) + (all-completions "" (mapcar 'list strings))))) + (cond + ;; + ;; If there is a common prefix, remove it and recurse on the suffixes. + ((> (length prefix) 0) + (let* ((length (length prefix)) + (suffixes (mapcar (lambda (s) (substring s length)) strings))) + (concat open-group + (regexp-quote prefix) (regexp-opt-group suffixes t t non-shy) + close-group))) + ;; + ;; If there are several one-character strings, remove them and recurse + ;; on the rest (first so the final regexp finds the longest match). + ((> (length letters) 1) + (let ((rest (let ((completion-regexp-list '("^..+$"))) + (all-completions "" (mapcar 'list strings))))) + (concat open-group + (regexp-opt-group rest nil nil non-shy) "\\|" (regexp-opt-charset letters) + close-group))) + ;; + ;; Otherwise, divide the list into those that start with a particular + ;; letter and those that do not, and recurse on them. + (t + (let* ((char (substring (car strings) 0 1)) + (half1 (all-completions char (mapcar 'list strings))) + (half2 (nthcdr (length half1) strings))) + (concat open-group + (regexp-opt-group half1 nil nil non-shy) "\\|" (regexp-opt-group half2 nil nil non-shy) + close-group))))))))) + +(defun regexp-opt-charset (chars) + ;; + ;; Return a regexp to match a character in CHARS. + ;; + ;; The basic idea is to find character ranges. Also we take care in the + ;; position of character set meta characters in the character set regexp. + ;; + (let* ((charwidth 256) ; Yeah, right. + ;; XEmacs: use bit-vectors instead of bool-vectors + (charmap (make-bit-vector charwidth 0)) + (charset "") + (bracket "") (dash "") (caret "")) + ;; + ;; Make a character map but extract character set meta characters. + (dolist (char (mapcar 'string-to-char chars)) + (case char + (?\] + (setq bracket "]")) + (?^ + (setq caret "^")) + (?- + (setq dash "-")) + (otherwise + ;; XEmacs: 1 + (aset charmap char 1)))) + ;; + ;; Make a character set from the map using ranges where applicable. + (dotimes (char charwidth) + (let ((start char)) + (while (and (< char charwidth) + ;; XEmacs: (not (zerop ...)) + (not (zerop (aref charmap char)))) + (incf char)) + (cond ((> char (+ start 3)) + (setq charset (format "%s%c-%c" charset start (1- char)))) + ((> char start) + (setq charset (format "%s%c" charset (setq char start))))))) + ;; + ;; Make sure a caret is not first and a dash is first or last. + (if (and (string-equal charset "") (string-equal bracket "")) + (concat "[" dash caret "]") + (concat "[" bracket charset caret dash "]")))) + +(provide 'regexp-opt) + +;;; regexp-opt.el ends here diff -r a9527fcdf77f -r c4c8a36043be lisp/update-elc-2.el --- a/lisp/update-elc-2.el Thu Feb 03 06:14:40 2005 +0000 +++ b/lisp/update-elc-2.el Thu Feb 03 07:11:28 2005 +0000 @@ -149,32 +149,25 @@ ;; way is slow, so we avoid it when possible. (when (file-exists-p (expand-file-name "REBUILD_AUTOLOADS" invocation-directory)) - (let ((generated-autoload-file (expand-file-name "auto-autoloads.el" dir)) - (autoload-package-name "auto")) ; feature prefix - ;; if we were instructed to rebuild the autoloads, force the file - ;; to be touched even w/o changes; otherwise, we won't ever stop - ;; being told to rebuild them. - (update-autoload-files (list dir) nil t) - (byte-recompile-file generated-autoload-file 0)) + ;; if we were instructed to rebuild the autoloads, force the file + ;; to be touched even w/o changes; otherwise, we won't ever stop + ;; being told to rebuild them. + (update-autoload-files dir "auto" nil t) + (byte-recompile-file (expand-file-name "auto-autoloads.el" dir) 0) (when (featurep 'mule) - (let* ((muledir (expand-file-name "../lisp/mule" (file-truename dir))) - (generated-autoload-file - (expand-file-name "auto-autoloads.el" muledir)) - (autoload-package-name "mule")) ; feature prefix + (let ((muledir (expand-file-name "../lisp/mule" (file-truename dir)))) ;; force here just like above. - (update-autoload-files (list muledir) nil t) - (byte-recompile-file generated-autoload-file 0)))) + (update-autoload-files muledir "mule" nil t) + (byte-recompile-file (expand-file-name "auto-autoloads.el" dir) 0)))) (when (featurep 'modules) (let* ((moddir (expand-file-name "../modules" (file-truename dir))) - (generated-autoload-file - (expand-file-name "auto-autoloads.el" moddir)) - (autoload-package-name "modules")) ; feature prefix - (update-autoload-files + (autofile (expand-file-name "auto-autoloads.el" moddir))) + (update-autoload-files (delete (concat (file-name-as-directory moddir) ".") (delete (concat (file-name-as-directory moddir) "..") (directory-files moddir t nil nil 0))) - t) - (byte-recompile-file generated-autoload-file 0))) + "modules" autofile) + (byte-recompile-file autofile 0))) ;; now load the (perhaps newly rebuilt) autoloads; we were called with ;; -no-autoloads so they're not already loaded. (load (expand-file-name "auto-autoloads" lisp-directory)) diff -r a9527fcdf77f -r c4c8a36043be lisp/update-elc.el --- a/lisp/update-elc.el Thu Feb 03 06:14:40 2005 +0000 +++ b/lisp/update-elc.el Thu Feb 03 07:11:28 2005 +0000 @@ -106,7 +106,7 @@ ;; early byte compilation. These are files loaded by update-elc.el in ;; order to do the compilation of all the rest of the files. (defvar lisp-files-needing-early-byte-compilation - '(;"easy-mmode" + '("easy-mmode" "autoload" "shadow" "cl-macs")) @@ -312,10 +312,10 @@ need-to-rebuild-mule-autoloads) (list "-l" "autoload")) (if need-to-rebuild-autoloads - (list "-f" "autoload-update-directory-autoloads" + (list "-f" "batch-update-directory-autoloads" "auto" source-lisp)) (if need-to-rebuild-mule-autoloads - (list "-f" "autoload-update-directory-autoloads" + (list "-f" "batch-update-directory-autoloads" "mule" source-lisp-mule)) (if need-to-recompile-autoloads (list "-f" "batch-byte-compile-one-file" diff -r a9527fcdf77f -r c4c8a36043be src/ChangeLog --- a/src/ChangeLog Thu Feb 03 06:14:40 2005 +0000 +++ b/src/ChangeLog Thu Feb 03 07:11:28 2005 +0000 @@ -1,3 +1,19 @@ +2005-02-02 Ben Wing + + * lread.c: + * lread.c (check_if_suppressed): + * lread.c (Fload_internal): + * lread.c (locate_file_in_directory_mapper): + * lread.c (readevalloop): + * lread.c (syms_of_lread): + * lread.c (vars_of_lread): + * lisp.h: + Remove undeeded Vload_file_name_internal_the_purecopy, + Qload_file_name -- use internal_bind_lisp_object instead of + specbind. + + Add load-suppress-alist. + 2005-02-02 Ben Wing * menubar.c: @@ -11,38 +27,6 @@ (This will be done in compare-menu-text.) Document that return value may be same string. -2005-02-02 Ben Wing - - * lread.c: - * lread.c (check_if_suppressed): - * lread.c (Fload_internal): - * lread.c (locate_file_in_directory_mapper): - * lread.c (readevalloop): - * lread.c (syms_of_lread): - * lread.c (vars_of_lread): - * menubar.c: - * menubar.c (Fcompare_menu_text): - * menubar.c (Fnormalize_menu_text): - * menubar.c (syms_of_menubar): - * menubar.c (vars_of_menubar): - -2004-11-09 Ben Wing - - * lisp.h: - - * lread.c: - * lread.c (check_if_suppressed): - * lread.c (Fload_internal): - * lread.c (locate_file_in_directory_mapper): - * lread.c (readevalloop): - * lread.c (syms_of_lread): - * lread.c (vars_of_lread): - Remove undeeded Vload_file_name_internal_the_purecopy, - Qload_file_name -- use internal_bind_lisp_object instead of - specbind. - - Add load-suppress-alist. - 2003-02-15 Ben Wing * syswindows.h: Define W32API_2_2 for w32api.h v2.2 or higher. diff -r a9527fcdf77f -r c4c8a36043be src/lisp.h --- a/src/lisp.h Thu Feb 03 06:14:40 2005 +0000 +++ b/src/lisp.h Thu Feb 03 07:11:28 2005 +0000 @@ -5294,8 +5294,7 @@ extern Lisp_Object Vinvocation_directory, Vinvocation_name; extern Lisp_Object Vlast_command, Vlast_command_char; extern Lisp_Object Vlast_command_event, Vlast_input_event; -extern Lisp_Object Vload_file_name_internal; -extern Lisp_Object Vload_file_name_internal_the_purecopy, Vload_history; +extern Lisp_Object Vload_file_name_internal, Vload_history; extern Lisp_Object Vload_path, Vmark_even_if_inactive, Vmenubar_configuration; extern Lisp_Object Vminibuf_preprompt, Vminibuf_prompt, Vminibuffer_zero; extern Lisp_Object Vmodule_directory, Vmswindows_downcase_file_names; diff -r a9527fcdf77f -r c4c8a36043be src/lread.c --- a/src/lread.c Thu Feb 03 06:14:40 2005 +0000 +++ b/src/lread.c Thu Feb 03 07:11:28 2005 +0000 @@ -59,8 +59,8 @@ #endif Lisp_Object Qvariable_domain; /* I18N3 */ Lisp_Object Vvalues, Vstandard_input, Vafter_load_alist; -Lisp_Object Qcurrent_load_list; -Lisp_Object Qload, Qload_file_name, Qload_internal, Qfset; +Lisp_Object Vload_suppress_alist; +Lisp_Object Qload, Qload_internal, Qfset; /* Hash-table that maps directory names to hashes of their contents. */ static Lisp_Object Vlocate_file_hash_table; @@ -118,8 +118,6 @@ our #$ checks are reliable. */ Lisp_Object Vload_file_name_internal; -Lisp_Object Vload_file_name_internal_the_purecopy; - /* Function to use for reading, in `load' and friends. */ Lisp_Object Vload_read_function; @@ -340,6 +338,50 @@ return Qnil; } +/* Check if NONRELOC/RELOC (an absolute filename) is suppressed according + to load-suppress-alist. */ +static int +check_if_suppressed (Ibyte *nonreloc, Lisp_Object reloc) +{ + Bytecount len; + + if (!NILP (reloc)) + { + nonreloc = XSTRING_DATA (reloc); + len = XSTRING_LENGTH (reloc); + } + else + len = qxestrlen (nonreloc); + + if (len >= 4 && !qxestrcmp_ascii (nonreloc + len - 4, ".elc")) + len -= 4; + else if (len >= 3 && !qxestrcmp_ascii (nonreloc + len - 3, ".el")) + len -= 3; + + EXTERNAL_LIST_LOOP_2 (acons, Vload_suppress_alist) + { + if (CONSP (acons) && STRINGP (XCAR (acons))) + { + Lisp_Object name = XCAR (acons); + if (XSTRING_LENGTH (name) == len && + !memcmp (XSTRING_DATA (name), nonreloc, len)) + { + struct gcpro gcpro1; + Lisp_Object val; + + GCPRO1 (reloc); + val = Feval (XCDR (acons)); + UNGCPRO; + + if (!NILP (val)) + return 1; + } + } + } + + return 0; +} + /* The plague is coming. Ring around the rosy, pocket full of posy, @@ -689,12 +731,11 @@ internal_bind_lisp_object (&Vload_descriptor_list, Fcons (make_int (fd), Vload_descriptor_list)); internal_bind_lisp_object (&Vload_file_name_internal, found); - internal_bind_lisp_object (&Vload_file_name_internal_the_purecopy, Qnil); /* this is not a simple internal_bind. */ record_unwind_protect (load_force_doc_string_unwind, Vload_force_doc_string_list); Vload_force_doc_string_list = Qnil; - specbind (Qload_file_name, found); + internal_bind_lisp_object (&Vload_file_name, found); #ifdef I18N3 /* set it to nil; a call to #'domain will set it. */ internal_bind_lisp_object (&Vfile_domain, Qnil); @@ -818,6 +859,9 @@ requirements. Allowed symbols are `exists', `executable', `writable', and `readable'. If MODE is nil, it defaults to `readable'. +Filenames are checked against `load-suppress-alist' to determine if they +should be ignored. + `locate-file' keeps hash tables of the directories it searches through, in order to speed things up. It tries valiantly to not get confused in the face of a changing and unpredictable environment, but can occasionally @@ -1024,11 +1068,14 @@ if (closure->fd >= 0) { - /* We succeeded; return this descriptor and filename. */ - if (closure->storeptr) - *closure->storeptr = build_intstring (fn); - - return 1; + if (!check_if_suppressed (fn, Qnil)) + { + /* We succeeded; return this descriptor and filename. */ + if (closure->storeptr) + *closure->storeptr = build_intstring (fn); + + return 1; + } } } /* Keep mapping. */ @@ -1178,7 +1225,7 @@ just look for one for which access(file,MODE) succeeds. In this case, returns a nonnegative value on success. On failure, returns -1. - If STOREPTR is nonzero, it points to a slot where the name of + If STOREPTR is non-nil, it points to a slot where the name of the file actually found should be stored as a Lisp string. Nil is stored there on failure. @@ -1377,7 +1424,7 @@ READCHARFUN (which can be a stream) to Lisp. --hniksic */ /*specbind (Qstandard_input, readcharfun);*/ - specbind (Qcurrent_load_list, Qnil); + internal_bind_lisp_object (&Vcurrent_load_list, Qnil); #ifdef COMPILED_FUNCTION_ANNOTATION_HACK Vcurrent_compiled_function_annotation = Qnil; @@ -3072,9 +3119,7 @@ DEFSYMBOL (Qstandard_input); DEFSYMBOL (Qread_char); - DEFSYMBOL (Qcurrent_load_list); DEFSYMBOL (Qload); - DEFSYMBOL (Qload_file_name); DEFSYMBOL (Qload_internal); DEFSYMBOL (Qfset); @@ -3141,6 +3186,16 @@ Non-nil iff inside of `load'. */ ); + DEFVAR_LISP ("load-suppress-alist", &Vload_suppress_alist /* +An alist of expressions controlling whether particular files can be loaded. +Each element looks like (FILENAME EXPR). +FILENAME should be a full pathname, but without the .el suffix. +When `load' is run and is about to load the specified file, it evaluates +the form to determine if the file can be loaded. +This variable is normally initialized automatically. +*/ ); + Vload_suppress_alist = Qnil; + DEFVAR_LISP ("after-load-alist", &Vafter_load_alist /* An alist of expressions to be evalled when particular files are loaded. Each element looks like (FILENAME FORMS...). @@ -3255,9 +3310,6 @@ Vload_file_name_internal = Qnil; staticpro (&Vload_file_name_internal); - Vload_file_name_internal_the_purecopy = Qnil; - staticpro (&Vload_file_name_internal_the_purecopy); - #ifdef COMPILED_FUNCTION_ANNOTATION_HACK Vcurrent_compiled_function_annotation = Qnil; staticpro (&Vcurrent_compiled_function_annotation);