diff options
| author | Stefan Monnier | 2013-06-13 18:24:52 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-06-13 18:24:52 -0400 |
| commit | de0503df97a507a523a192e877a8d5c7439c4846 (patch) | |
| tree | 0753a678f85a7ea1a2eb46b81067e8a5d6dfc1e0 | |
| parent | bc5c8c5a6a1956122284468879862b1850dc3b5d (diff) | |
| download | emacs-de0503df97a507a523a192e877a8d5c7439c4846.tar.gz emacs-de0503df97a507a523a192e877a8d5c7439c4846.zip | |
* lisp/subr.el (with-eval-after-load): New macro.
(eval-after-load): Allow form to be a function.
take advantage of lexical-binding.
(do-after-load-evaluation): Use dolist and adjust to new format.
* lisp/simple.el (bad-packages-alist): Use dolist and with-eval-after-load.
* doc/lispref/loading.texi (Hooks for Loading): Document with-eval-after-load
instead of eval-after-load. Don't document after-load-alist.
* src/lread.c (syms_of_lread):
* src/fns.c (Fprovide): Adjust to new format of after-load-alist.
| -rw-r--r-- | doc/lispref/ChangeLog | 5 | ||||
| -rw-r--r-- | doc/lispref/loading.texi | 36 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/ChangeLog | 8 | ||||
| -rw-r--r-- | lisp/simple.el | 11 | ||||
| -rw-r--r-- | lisp/subr.el | 74 | ||||
| -rw-r--r-- | src/ChangeLog | 5 | ||||
| -rw-r--r-- | src/fns.c | 5 | ||||
| -rw-r--r-- | src/lread.c | 6 |
9 files changed, 88 insertions, 67 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 259bf9a78a6..e14f7543443 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2013-06-13 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * loading.texi (Hooks for Loading): Don't document after-load-alist. | ||
| 4 | Document with-eval-after-load instead of eval-after-load. | ||
| 5 | |||
| 1 | 2013-06-11 Xue Fuqiao <xfq.free@gmail.com> | 6 | 2013-06-11 Xue Fuqiao <xfq.free@gmail.com> |
| 2 | 7 | ||
| 3 | * files.texi (File Name Expansion): Make the example more | 8 | * files.texi (File Name Expansion): Make the example more |
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 5c92307f7d5..4c0f0d73e41 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi | |||
| @@ -990,19 +990,18 @@ file that was just loaded. | |||
| 990 | @end defvar | 990 | @end defvar |
| 991 | 991 | ||
| 992 | If you want code to be executed when a @emph{particular} library is | 992 | If you want code to be executed when a @emph{particular} library is |
| 993 | loaded, use the function @code{eval-after-load}: | 993 | loaded, use the macro @code{with-eval-after-load}: |
| 994 | 994 | ||
| 995 | @defun eval-after-load library form | 995 | @defmac with-eval-after-load library body@dots{} |
| 996 | This function arranges to evaluate @var{form} at the end of loading | 996 | This macro arranges to evaluate @var{body} at the end of loading |
| 997 | the file @var{library}, each time @var{library} is loaded. If | 997 | the file @var{library}, each time @var{library} is loaded. If |
| 998 | @var{library} is already loaded, it evaluates @var{form} right away. | 998 | @var{library} is already loaded, it evaluates @var{body} right away. |
| 999 | Don't forget to quote @var{form}! | ||
| 1000 | 999 | ||
| 1001 | You don't need to give a directory or extension in the file name | 1000 | You don't need to give a directory or extension in the file name |
| 1002 | @var{library}. Normally, you just give a bare file name, like this: | 1001 | @var{library}. Normally, you just give a bare file name, like this: |
| 1003 | 1002 | ||
| 1004 | @example | 1003 | @example |
| 1005 | (eval-after-load "edebug" '(def-edebug-spec c-point t)) | 1004 | (with-eval-after-load "edebug" (def-edebug-spec c-point t)) |
| 1006 | @end example | 1005 | @end example |
| 1007 | 1006 | ||
| 1008 | To restrict which files can trigger the evaluation, include a | 1007 | To restrict which files can trigger the evaluation, include a |
| @@ -1014,16 +1013,16 @@ example, @file{my_inst.elc} or @file{my_inst.elc.gz} in some directory | |||
| 1014 | @file{my_inst.el}: | 1013 | @file{my_inst.el}: |
| 1015 | 1014 | ||
| 1016 | @example | 1015 | @example |
| 1017 | (eval-after-load "foo/bar/my_inst.elc" @dots{}) | 1016 | (with-eval-after-load "foo/bar/my_inst.elc" @dots{}) |
| 1018 | @end example | 1017 | @end example |
| 1019 | 1018 | ||
| 1020 | @var{library} can also be a feature (i.e., a symbol), in which case | 1019 | @var{library} can also be a feature (i.e., a symbol), in which case |
| 1021 | @var{form} is evaluated at the end of any file where | 1020 | @var{body} is evaluated at the end of any file where |
| 1022 | @code{(provide @var{library})} is called. | 1021 | @code{(provide @var{library})} is called. |
| 1023 | 1022 | ||
| 1024 | An error in @var{form} does not undo the load, but does prevent | 1023 | An error in @var{body} does not undo the load, but does prevent |
| 1025 | execution of the rest of @var{form}. | 1024 | execution of the rest of @var{body}. |
| 1026 | @end defun | 1025 | @end defmac |
| 1027 | 1026 | ||
| 1028 | Normally, well-designed Lisp programs should not use | 1027 | Normally, well-designed Lisp programs should not use |
| 1029 | @code{eval-after-load}. If you need to examine and set the variables | 1028 | @code{eval-after-load}. If you need to examine and set the variables |
| @@ -1031,18 +1030,3 @@ defined in another library (those meant for outside use), you can do | |||
| 1031 | it immediately---there is no need to wait until the library is loaded. | 1030 | it immediately---there is no need to wait until the library is loaded. |
| 1032 | If you need to call functions defined by that library, you should load | 1031 | If you need to call functions defined by that library, you should load |
| 1033 | the library, preferably with @code{require} (@pxref{Named Features}). | 1032 | the library, preferably with @code{require} (@pxref{Named Features}). |
| 1034 | |||
| 1035 | @defvar after-load-alist | ||
| 1036 | This variable stores an alist built by @code{eval-after-load}, | ||
| 1037 | containing the expressions to evaluate when certain libraries are | ||
| 1038 | loaded. Each element looks like this: | ||
| 1039 | |||
| 1040 | @example | ||
| 1041 | (@var{regexp-or-feature} @var{forms}@dots{}) | ||
| 1042 | @end example | ||
| 1043 | |||
| 1044 | The key @var{regexp-or-feature} is either a regular expression or a | ||
| 1045 | symbol, and the value is a list of forms. The forms are evaluated | ||
| 1046 | when the key matches the absolute true name or feature name of the | ||
| 1047 | library being loaded. | ||
| 1048 | @end defvar | ||
| @@ -452,8 +452,9 @@ file using `set-file-extended-attributes'. | |||
| 452 | 452 | ||
| 453 | * Lisp Changes in Emacs 24.4 | 453 | * Lisp Changes in Emacs 24.4 |
| 454 | 454 | ||
| 455 | FIXME - someone who knows what they are talking about, please improve | 455 | +++ |
| 456 | this - see http://debbugs.gnu.org/14596 | 456 | ** New macro with-eval-after-load. Like eval-after-load, but better behaved. |
| 457 | |||
| 457 | ** The default file coding for Emacs Lisp files is now utf-8. | 458 | ** The default file coding for Emacs Lisp files is now utf-8. |
| 458 | (See file-coding-system-alist.) In most cases, this change is | 459 | (See file-coding-system-alist.) In most cases, this change is |
| 459 | totally transparent. Files that contain unusual characters but do | 460 | totally transparent. Files that contain unusual characters but do |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 98e0382853d..88f218d15f3 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2013-06-13 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * subr.el (with-eval-after-load): New macro. | ||
| 4 | (eval-after-load): Allow form to be a function. | ||
| 5 | take advantage of lexical-binding. | ||
| 6 | (do-after-load-evaluation): Use dolist and adjust to new format. | ||
| 7 | * simple.el (bad-packages-alist): Use dolist and with-eval-after-load. | ||
| 8 | |||
| 1 | 2013-06-13 Juri Linkov <juri@jurta.org> | 9 | 2013-06-13 Juri Linkov <juri@jurta.org> |
| 2 | 10 | ||
| 3 | * replace.el (perform-replace): Display "symbol " and other search | 11 | * replace.el (perform-replace): Display "symbol " and other search |
diff --git a/lisp/simple.el b/lisp/simple.el index 15bf8779f56..3fd94e96d33 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -7295,8 +7295,7 @@ version and use the one distributed with Emacs.")) | |||
| 7295 | "Alist of packages known to cause problems in this version of Emacs. | 7295 | "Alist of packages known to cause problems in this version of Emacs. |
| 7296 | Each element has the form (PACKAGE SYMBOL REGEXP STRING). | 7296 | Each element has the form (PACKAGE SYMBOL REGEXP STRING). |
| 7297 | PACKAGE is either a regular expression to match file names, or a | 7297 | PACKAGE is either a regular expression to match file names, or a |
| 7298 | symbol (a feature name); see the documentation of | 7298 | symbol (a feature name), like for `with-eval-after-load'. |
| 7299 | `after-load-alist', to which this variable adds functions. | ||
| 7300 | SYMBOL is either the name of a string variable, or `t'. Upon | 7299 | SYMBOL is either the name of a string variable, or `t'. Upon |
| 7301 | loading PACKAGE, if SYMBOL is t or matches REGEXP, display a | 7300 | loading PACKAGE, if SYMBOL is t or matches REGEXP, display a |
| 7302 | warning using STRING as the message.") | 7301 | warning using STRING as the message.") |
| @@ -7314,10 +7313,10 @@ warning using STRING as the message.") | |||
| 7314 | (display-warning package (nth 3 list) :warning))) | 7313 | (display-warning package (nth 3 list) :warning))) |
| 7315 | (error nil))) | 7314 | (error nil))) |
| 7316 | 7315 | ||
| 7317 | (mapc (lambda (elem) | 7316 | (dolist (elem bad-packages-alist) |
| 7318 | (eval-after-load (car elem) `(bad-package-check ',(car elem)))) | 7317 | (let ((pkg (car elem))) |
| 7319 | bad-packages-alist) | 7318 | (with-eval-after-load pkg |
| 7320 | 7319 | (bad-package-check pkg)))) | |
| 7321 | 7320 | ||
| 7322 | (provide 'simple) | 7321 | (provide 'simple) |
| 7323 | 7322 | ||
diff --git a/lisp/subr.el b/lisp/subr.el index 380b2ba66ee..05f9167c699 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -3729,6 +3729,8 @@ Return nil if there isn't one." | |||
| 3729 | (defun eval-after-load (file form) | 3729 | (defun eval-after-load (file form) |
| 3730 | "Arrange that if FILE is loaded, FORM will be run immediately afterwards. | 3730 | "Arrange that if FILE is loaded, FORM will be run immediately afterwards. |
| 3731 | If FILE is already loaded, evaluate FORM right now. | 3731 | If FILE is already loaded, evaluate FORM right now. |
| 3732 | FORM can be an Elisp expression (in which case it's passed to `eval'), | ||
| 3733 | or a function (in which case it's passed to `funcall' with no argument). | ||
| 3732 | 3734 | ||
| 3733 | If a matching file is loaded again, FORM will be evaluated again. | 3735 | If a matching file is loaded again, FORM will be evaluated again. |
| 3734 | 3736 | ||
| @@ -3756,43 +3758,58 @@ Usually FILE is just a library name like \"font-lock\" or a feature name | |||
| 3756 | like 'font-lock. | 3758 | like 'font-lock. |
| 3757 | 3759 | ||
| 3758 | This function makes or adds to an entry on `after-load-alist'." | 3760 | This function makes or adds to an entry on `after-load-alist'." |
| 3761 | (declare (compiler-macro | ||
| 3762 | (lambda (whole) | ||
| 3763 | (if (eq 'quote (car-safe form)) | ||
| 3764 | ;; Quote with lambda so the compiler can look inside. | ||
| 3765 | `(eval-after-load ,file (lambda () ,(nth 1 form))) | ||
| 3766 | whole)))) | ||
| 3759 | ;; Add this FORM into after-load-alist (regardless of whether we'll be | 3767 | ;; Add this FORM into after-load-alist (regardless of whether we'll be |
| 3760 | ;; evaluating it now). | 3768 | ;; evaluating it now). |
| 3761 | (let* ((regexp-or-feature | 3769 | (let* ((regexp-or-feature |
| 3762 | (if (stringp file) | 3770 | (if (stringp file) |
| 3763 | (setq file (purecopy (load-history-regexp file))) | 3771 | (setq file (purecopy (load-history-regexp file))) |
| 3764 | file)) | 3772 | file)) |
| 3765 | (elt (assoc regexp-or-feature after-load-alist))) | 3773 | (elt (assoc regexp-or-feature after-load-alist)) |
| 3774 | (func | ||
| 3775 | (if (functionp form) form | ||
| 3776 | ;; Try to use the "current" lexical/dynamic mode for `form'. | ||
| 3777 | (eval `(lambda () ,form) lexical-binding)))) | ||
| 3766 | (unless elt | 3778 | (unless elt |
| 3767 | (setq elt (list regexp-or-feature)) | 3779 | (setq elt (list regexp-or-feature)) |
| 3768 | (push elt after-load-alist)) | 3780 | (push elt after-load-alist)) |
| 3769 | ;; Make sure `form' is evalled in the current lexical/dynamic code. | ||
| 3770 | (setq form `(funcall ',(eval `(lambda () ,form) lexical-binding))) | ||
| 3771 | ;; Is there an already loaded file whose name (or `provide' name) | 3781 | ;; Is there an already loaded file whose name (or `provide' name) |
| 3772 | ;; matches FILE? | 3782 | ;; matches FILE? |
| 3773 | (prog1 (if (if (stringp file) | 3783 | (prog1 (if (if (stringp file) |
| 3774 | (load-history-filename-element regexp-or-feature) | 3784 | (load-history-filename-element regexp-or-feature) |
| 3775 | (featurep file)) | 3785 | (featurep file)) |
| 3776 | (eval form)) | 3786 | (funcall func)) |
| 3777 | (when (symbolp regexp-or-feature) | 3787 | (let ((delayed-func |
| 3778 | ;; For features, the after-load-alist elements get run when `provide' is | 3788 | (if (not (symbolp regexp-or-feature)) func |
| 3779 | ;; called rather than at the end of the file. So add an indirection to | 3789 | ;; For features, the after-load-alist elements get run when |
| 3780 | ;; make sure that `form' is really run "after-load" in case the provide | 3790 | ;; `provide' is called rather than at the end of the file. |
| 3781 | ;; call happens early. | 3791 | ;; So add an indirection to make sure that `func' is really run |
| 3782 | (setq form | 3792 | ;; "after-load" in case the provide call happens early. |
| 3783 | `(if load-file-name | 3793 | (lambda () |
| 3784 | (let ((fun (make-symbol "eval-after-load-helper"))) | 3794 | (if (not load-file-name) |
| 3785 | (fset fun `(lambda (file) | 3795 | ;; Not being provided from a file, run func right now. |
| 3786 | (if (not (equal file ',load-file-name)) | 3796 | (funcall func) |
| 3787 | nil | 3797 | (let ((lfn load-file-name)) |
| 3788 | (remove-hook 'after-load-functions ',fun) | 3798 | (letrec ((fun (lambda (file) |
| 3789 | ,',form))) | 3799 | (when (equal file lfn) |
| 3790 | (add-hook 'after-load-functions fun)) | 3800 | (remove-hook 'after-load-functions fun) |
| 3791 | ;; Not being provided from a file, run form right now. | 3801 | (funcall func))))) |
| 3792 | ,form))) | 3802 | (add-hook 'after-load-functions fun)))))))) |
| 3793 | ;; Add FORM to the element unless it's already there. | 3803 | ;; Add FORM to the element unless it's already there. |
| 3794 | (unless (member form (cdr elt)) | 3804 | (unless (member delayed-func (cdr elt)) |
| 3795 | (nconc elt (list form)))))) | 3805 | (nconc elt (list delayed-func))))))) |
| 3806 | |||
| 3807 | (defmacro with-eval-after-load (file &rest body) | ||
| 3808 | "Execute BODY after FILE is loaded. | ||
| 3809 | FILE is normally a feature name, but it can also be a file name, | ||
| 3810 | in case that file does not provide any feature." | ||
| 3811 | (declare (indent 1) (debug t)) | ||
| 3812 | `(eval-after-load ,file (lambda () ,@body))) | ||
| 3796 | 3813 | ||
| 3797 | (defvar after-load-functions nil | 3814 | (defvar after-load-functions nil |
| 3798 | "Special hook run after loading a file. | 3815 | "Special hook run after loading a file. |
| @@ -3804,12 +3821,11 @@ name of the file just loaded.") | |||
| 3804 | ABS-FILE, a string, should be the absolute true name of a file just loaded. | 3821 | ABS-FILE, a string, should be the absolute true name of a file just loaded. |
| 3805 | This function is called directly from the C code." | 3822 | This function is called directly from the C code." |
| 3806 | ;; Run the relevant eval-after-load forms. | 3823 | ;; Run the relevant eval-after-load forms. |
| 3807 | (mapc #'(lambda (a-l-element) | 3824 | (dolist (a-l-element after-load-alist) |
| 3808 | (when (and (stringp (car a-l-element)) | 3825 | (when (and (stringp (car a-l-element)) |
| 3809 | (string-match-p (car a-l-element) abs-file)) | 3826 | (string-match-p (car a-l-element) abs-file)) |
| 3810 | ;; discard the file name regexp | 3827 | ;; discard the file name regexp |
| 3811 | (mapc #'eval (cdr a-l-element)))) | 3828 | (mapc #'funcall (cdr a-l-element)))) |
| 3812 | after-load-alist) | ||
| 3813 | ;; Complain when the user uses obsolete files. | 3829 | ;; Complain when the user uses obsolete files. |
| 3814 | (when (string-match-p "/obsolete/[^/]*\\'" abs-file) | 3830 | (when (string-match-p "/obsolete/[^/]*\\'" abs-file) |
| 3815 | (run-with-timer 0 nil | 3831 | (run-with-timer 0 nil |
diff --git a/src/ChangeLog b/src/ChangeLog index 4d6e669612f..827092e7f8a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2013-06-13 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * lread.c (syms_of_lread): | ||
| 4 | * fns.c (Fprovide): Adjust to new format of after-load-alist. | ||
| 5 | |||
| 1 | 2013-06-13 Kelly Dean <kellydeanch@yahoo.com> (tiny change) | 6 | 2013-06-13 Kelly Dean <kellydeanch@yahoo.com> (tiny change) |
| 2 | 7 | ||
| 3 | * fileio.c (Fdo_auto_save): Trap errors in auto-save-hook. (Bug#14479) | 8 | * fileio.c (Fdo_auto_save): Trap errors in auto-save-hook. (Bug#14479) |
| @@ -2545,6 +2545,8 @@ SUBFEATURE can be used to check a specific subfeature of FEATURE. */) | |||
| 2545 | return (NILP (tem)) ? Qnil : Qt; | 2545 | return (NILP (tem)) ? Qnil : Qt; |
| 2546 | } | 2546 | } |
| 2547 | 2547 | ||
| 2548 | static Lisp_Object Qfuncall; | ||
| 2549 | |||
| 2548 | DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0, | 2550 | DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0, |
| 2549 | doc: /* Announce that FEATURE is a feature of the current Emacs. | 2551 | doc: /* Announce that FEATURE is a feature of the current Emacs. |
| 2550 | The optional argument SUBFEATURES should be a list of symbols listing | 2552 | The optional argument SUBFEATURES should be a list of symbols listing |
| @@ -2567,7 +2569,7 @@ particular subfeatures supported in this version of FEATURE. */) | |||
| 2567 | /* Run any load-hooks for this file. */ | 2569 | /* Run any load-hooks for this file. */ |
| 2568 | tem = Fassq (feature, Vafter_load_alist); | 2570 | tem = Fassq (feature, Vafter_load_alist); |
| 2569 | if (CONSP (tem)) | 2571 | if (CONSP (tem)) |
| 2570 | Fprogn (XCDR (tem)); | 2572 | Fmapc (Qfuncall, XCDR (tem)); |
| 2571 | 2573 | ||
| 2572 | return feature; | 2574 | return feature; |
| 2573 | } | 2575 | } |
| @@ -4866,6 +4868,7 @@ syms_of_fns (void) | |||
| 4866 | Used by `featurep' and `require', and altered by `provide'. */); | 4868 | Used by `featurep' and `require', and altered by `provide'. */); |
| 4867 | Vfeatures = Fcons (intern_c_string ("emacs"), Qnil); | 4869 | Vfeatures = Fcons (intern_c_string ("emacs"), Qnil); |
| 4868 | DEFSYM (Qsubfeatures, "subfeatures"); | 4870 | DEFSYM (Qsubfeatures, "subfeatures"); |
| 4871 | DEFSYM (Qfuncall, "funcall"); | ||
| 4869 | 4872 | ||
| 4870 | #ifdef HAVE_LANGINFO_CODESET | 4873 | #ifdef HAVE_LANGINFO_CODESET |
| 4871 | DEFSYM (Qcodeset, "codeset"); | 4874 | DEFSYM (Qcodeset, "codeset"); |
diff --git a/src/lread.c b/src/lread.c index 3ca644bb45b..b57665e365c 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -4485,15 +4485,15 @@ customize `jka-compr-load-suffixes' rather than the present variable. */); | |||
| 4485 | DEFSYM (Qload_in_progress, "load-in-progress"); | 4485 | DEFSYM (Qload_in_progress, "load-in-progress"); |
| 4486 | 4486 | ||
| 4487 | DEFVAR_LISP ("after-load-alist", Vafter_load_alist, | 4487 | DEFVAR_LISP ("after-load-alist", Vafter_load_alist, |
| 4488 | doc: /* An alist of expressions to be evalled when particular files are loaded. | 4488 | doc: /* An alist of functions to be evalled when particular files are loaded. |
| 4489 | Each element looks like (REGEXP-OR-FEATURE FORMS...). | 4489 | Each element looks like (REGEXP-OR-FEATURE FUNCS...). |
| 4490 | 4490 | ||
| 4491 | REGEXP-OR-FEATURE is either a regular expression to match file names, or | 4491 | REGEXP-OR-FEATURE is either a regular expression to match file names, or |
| 4492 | a symbol \(a feature name). | 4492 | a symbol \(a feature name). |
| 4493 | 4493 | ||
| 4494 | When `load' is run and the file-name argument matches an element's | 4494 | When `load' is run and the file-name argument matches an element's |
| 4495 | REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol | 4495 | REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol |
| 4496 | REGEXP-OR-FEATURE, the FORMS in the element are executed. | 4496 | REGEXP-OR-FEATURE, the FUNCS in the element are called. |
| 4497 | 4497 | ||
| 4498 | An error in FORMS does not undo the load, but does prevent execution of | 4498 | An error in FORMS does not undo the load, but does prevent execution of |
| 4499 | the rest of the FORMS. */); | 4499 | the rest of the FORMS. */); |