Mercurial > emacs
comparison lisp/emacs-lisp/advice.el @ 8445:81f7b5d9b990
New handling of automatic advice activation that
exploits modified built-in versions of `fset' and `defalias' which
take care of this functionality directly:
(ad-start-advice-on-load, ad-activate-on-definition)
(ad-definition-hooks, ad-enable-definition-hooks, ad-defined-function)
(ad-advised-definers, ad-advised-byte-compilers, byte-constant)
(byte-constant-limit, byte-constant2, byte-fset)
(ad-byte-code-fset-regexp): Variables deleted.
(ad-activate-defined-function, ad-find-fset-in-byte-code)
(ad-scan-byte-code-for-fsets, ad-advised-byte-code)
(ad-recover-byte-code, ad-enable-definition-hooks)
(ad-disable-definition-hooks): Functions deleted.
(defun, defmacro, fset, defalias, define-function)
(byte-compile-from-buffer, byte-compile-top-level): Removed `defadvice'
for these functions.
(ad-save-real-definitions): Removed saving of `byte-code'.
(ad-activate-off): New dummy function.
(ad-activate-on): New name for `ad-activate'. All calls changed.
(ad-with-auto-activation-disabled): New macro prevents automatic
advice activation.
(ad-safe-fset): New function, used instead of `ad-real-fset'.
(ad-compile-function): Disable automatic advice activation while
compiling, because `byte-compile' uses `fset'.
(ad-activate-on): Renamed from `ad-activate'. Avoid recursive calls.
(ad-activate-on-top-level): New variable.
(ad-start-advice, ad-stop-advice, ad-recover-normality): Modified to
achieve de/activation of automatic advice activation by setting the
definition of `ad-activate' to `ad-activate-on' or `ad-activate-off'.
(ad-start-advice): Is now called unconditionally when Advice is loaded.
Made compilation behavior of advised definitions customizable, since
loading the byte-compiler takes some time and is not always worth the
cost, e.g., if one only wants to make a few simple modifications:
(ad-default-compilation-action): New variable which specifies whether
to compile an advised definition in case the COMPILE argument to
`ad-activate-on' or one of its friends was supplied as nil.
(ad-preactivate-advice): Supply negative COMPILE argument to prevent
compilation.
(ad-should-compile): New function.
(ad-activate-advised-definition): Use `ad-should-compile' to determine
whether an advised definition should get compiled.
(ad-activate-on, ad-update, ad-activate-regexp, ad-update-regexp)
(ad-activate-all): Doc fixes.
(ad-update): Leave handling of COMPILE up to `ad-activate-on'.
Extracted construction of freeze-advices from `defadvice':
(ad-make-freeze-definition): New function.
(defadvice): Use `ad-make-freeze-definition' to construct frozen defs.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 04 Aug 1994 21:40:49 +0000 |
parents | 829b83e91e8b |
children | a95ca44cec95 |
comparison
equal
deleted
inserted
replaced
8444:841f2c8ae5bb | 8445:81f7b5d9b990 |
---|---|
2 | 2 |
3 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu> | 5 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu> |
6 ;; Created: 12 Dec 1992 | 6 ;; Created: 12 Dec 1992 |
7 ;; Version: advice.el,v 2.11 1994/02/24 22:51:43 hans Exp | 7 ;; Version: advice.el,v 2.13 1994/08/03 23:27:05 hans Exp |
8 ;; Keywords: extensions, lisp, tools | 8 ;; Keywords: extensions, lisp, tools |
9 | 9 |
10 ;; This file is part of GNU Emacs. | 10 ;; This file is part of GNU Emacs. |
11 | 11 |
12 ;; GNU Emacs is free software; you can redistribute it and/or modify | 12 ;; GNU Emacs is free software; you can redistribute it and/or modify |
24 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 24 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | 25 |
26 ;; LCD Archive Entry: | 26 ;; LCD Archive Entry: |
27 ;; advice|Hans Chalupsky|hans@cs.buffalo.edu| | 27 ;; advice|Hans Chalupsky|hans@cs.buffalo.edu| |
28 ;; Overloading mechanism for Emacs Lisp functions| | 28 ;; Overloading mechanism for Emacs Lisp functions| |
29 ;; 1994/02/24 22:51:43|2.11|~/packages/advice.el.Z| | 29 ;; 1994/08/03 23:27:05|2.13|~/packages/advice.el.Z| |
30 | 30 |
31 | 31 |
32 ;;; Commentary: | 32 ;;; Commentary: |
33 | 33 |
34 ;; NOTE: This documentation is slightly out of date. In particular, all the | 34 ;; NOTE: This documentation is slightly out of date. In particular, all the |
66 ;; - Allows the specification of a different argument list for the advised | 66 ;; - Allows the specification of a different argument list for the advised |
67 ;; version of a function. | 67 ;; version of a function. |
68 ;; - Advised functions can be byte-compiled either at file-compile time | 68 ;; - Advised functions can be byte-compiled either at file-compile time |
69 ;; (see preactivation) or activation time. | 69 ;; (see preactivation) or activation time. |
70 ;; - Separation of advice definition and activation | 70 ;; - Separation of advice definition and activation |
71 ;; - Provides generally accessible function definition (after) hooks | 71 ;; - Forward advice is possible, that is |
72 ;; - Forward advice is possible (an application of definition hooks), that is | |
73 ;; as yet undefined or autoload functions can be advised without having to | 72 ;; as yet undefined or autoload functions can be advised without having to |
74 ;; preload the file in which they are defined. | 73 ;; preload the file in which they are defined. |
75 ;; - Forward redefinition is possible because around advice can be used to | 74 ;; - Forward redefinition is possible because around advice can be used to |
76 ;; completely redefine a function. | 75 ;; completely redefine a function. |
77 ;; - A caching mechanism for advised definition provides for cheap deactivation | 76 ;; - A caching mechanism for advised definition provides for cheap deactivation |
81 ;; the advice mechanism. | 80 ;; the advice mechanism. |
82 ;; - En/disablement mechanism allows the use of different "views" of advised | 81 ;; - En/disablement mechanism allows the use of different "views" of advised |
83 ;; functions depending on what pieces of advice are currently en/disabled | 82 ;; functions depending on what pieces of advice are currently en/disabled |
84 ;; - Provides manipulation mechanisms for sets of advised functions via | 83 ;; - Provides manipulation mechanisms for sets of advised functions via |
85 ;; regular expressions that match advice names | 84 ;; regular expressions that match advice names |
86 ;; - Allows definition of load-hooks for arbitrary Emacs Lisp files without | |
87 ;; modification of these files | |
88 | 85 |
89 ;; @ How to get Advice for Emacs-18: | 86 ;; @ How to get Advice for Emacs-18: |
90 ;; ================================= | 87 ;; ================================= |
91 ;; `advice18.el', a version of Advice that also works in Emacs-18 is available | 88 ;; `advice18.el', a version of Advice that also works in Emacs-18 is available |
92 ;; either via anonymous ftp from `ftp.cs.buffalo.edu (128.205.32.9)' with | 89 ;; either via anonymous ftp from `ftp.cs.buffalo.edu (128.205.32.9)' with |
112 ;; The latter three are actual headings which you can search for | 109 ;; The latter three are actual headings which you can search for |
113 ;; directly in case `outline-mode' doesn't work for you. | 110 ;; directly in case `outline-mode' doesn't work for you. |
114 | 111 |
115 ;; @ Restrictions: | 112 ;; @ Restrictions: |
116 ;; =============== | 113 ;; =============== |
117 ;; - This version of Advice only works for Emacs-19 or Lucid Emacs. | 114 ;; - This version of Advice only works for Emacs 19.26 and later. It uses |
115 ;; new versions of the built-in functions `fset/defalias' which are not | |
116 ;; yet available in Lucid Emacs, hence, it won't work there. | |
118 ;; - Advised functions/macros/subrs will only exhibit their advised behavior | 117 ;; - Advised functions/macros/subrs will only exhibit their advised behavior |
119 ;; when they are invoked via their function cell. This means that advice will | 118 ;; when they are invoked via their function cell. This means that advice will |
120 ;; not work for the following: | 119 ;; not work for the following: |
121 ;; + advised subrs that are called directly from other subrs or C-code | 120 ;; + advised subrs that are called directly from other subrs or C-code |
122 ;; + advised subrs that got replaced with their byte-code during | 121 ;; + advised subrs that got replaced with their byte-code during |
123 ;; byte-compilation (e.g., car) | 122 ;; byte-compilation (e.g., car) |
124 ;; + advised macros which were expanded during byte-compilation before | 123 ;; + advised macros which were expanded during byte-compilation before |
125 ;; their advice was activated. | 124 ;; their advice was activated. |
126 | 125 |
127 ;; @ Known bug: | |
128 ;; ============ | |
129 ;; - Using automatic activation of (forward) advice will break the | |
130 ;; function `interactive-p' when it is used in the body of a `catch' | |
131 ;; (this problem will go away once automatic advice activation gets | |
132 ;; supported by built-in functions). | |
133 | |
134 ;; @ Credits: | 126 ;; @ Credits: |
135 ;; ========== | 127 ;; ========== |
136 ;; This package is an extension and generalization of packages such as | 128 ;; This package is an extension and generalization of packages such as |
137 ;; insert-hooks.el written by Noah S. Friedman, and advise.el written by | 129 ;; insert-hooks.el written by Noah S. Friedman, and advise.el written by |
138 ;; Raul J. Acevedo. Some ideas used in here come from these packages, | 130 ;; Raul J. Acevedo. Some ideas used in here come from these packages, |
149 ;; @ Safety Rules and Emergency Exits: | 141 ;; @ Safety Rules and Emergency Exits: |
150 ;; =================================== | 142 ;; =================================== |
151 ;; Before we begin: CAUTION!! | 143 ;; Before we begin: CAUTION!! |
152 ;; Advice provides you with a lot of rope to hang yourself on very | 144 ;; Advice provides you with a lot of rope to hang yourself on very |
153 ;; easily accessible trees, so, here are a few important things you | 145 ;; easily accessible trees, so, here are a few important things you |
154 ;; should know: Once Advice has been started with `ad-start-advice' it | 146 ;; should know: Once Advice has been started with `ad-start-advice' |
155 ;; generates advised definitions of the `documentation' function, and, | 147 ;; (which happens automatically when you load this file), it |
156 ;; if definition hooks are enabled (e.g., for forward advice), also of | 148 ;; generates an advised definition of the `documentation' function, and |
157 ;; `defun', `defmacro' and `fset' (if you use Jamie Zawinski's (jwz) | 149 ;; it will enable automatic advice activation when functions get defined. |
158 ;; optimizing byte-compiler as standardly used in Emacs-19 and | 150 ;; All of this can be undone at any time with `M-x ad-stop-advice'. |
159 ;; Lucid Emacs-19 (Lemacs), then enabling definition hooks will also | |
160 ;; redefine the `byte-code' subr). All these changes can be undone at | |
161 ;; any time with `M-x ad-stop-advice'. | |
162 ;; | 151 ;; |
163 ;; If you experience any strange behavior/errors etc. that you attribute to | 152 ;; If you experience any strange behavior/errors etc. that you attribute to |
164 ;; Advice or to some ill-advised function do one of the following: | 153 ;; Advice or to some ill-advised function do one of the following: |
165 | 154 |
166 ;; - M-x ad-deactivate FUNCTION (if you have a definite suspicion what | 155 ;; - M-x ad-deactivate FUNCTION (if you have a definite suspicion what |
188 ;; I use it extensively and haven't run into any serious trouble in a long | 177 ;; I use it extensively and haven't run into any serious trouble in a long |
189 ;; time. Just wanted you to be warned. | 178 ;; time. Just wanted you to be warned. |
190 | 179 |
191 ;; @ Customization: | 180 ;; @ Customization: |
192 ;; ================ | 181 ;; ================ |
193 ;; Part of the advice magic does not start until you call `ad-start-advice' | |
194 ;; which you can either do interactively, explicitly in your .emacs, or by | |
195 ;; putting | |
196 ;; | |
197 ;; (setq ad-start-advice-on-load t) | |
198 ;; | |
199 ;; into your .emacs which will automatically start advice when the file gets | |
200 ;; loaded. | |
201 | |
202 ;; If you want to be able to forward advise functions, that is to advise them | |
203 ;; when they are not yet defined or defined as autoloads, then you should put | |
204 ;; the following into your .emacs | |
205 ;; | |
206 ;; (setq ad-activate-on-definition t) | |
207 ;; | |
208 ;; which will activate all advice at the time the function gets actually | |
209 ;; defined/loaded. The value of this variable will not have any effect until | |
210 ;; `ad-start-advice' gets executed. | |
211 | 182 |
212 ;; Look at the documentation of `ad-redefinition-action' for possible values | 183 ;; Look at the documentation of `ad-redefinition-action' for possible values |
213 ;; of this variable. Its default value is `warn' which will print a warning | 184 ;; of this variable. Its default value is `warn' which will print a warning |
214 ;; message when an already defined advised function gets redefined with a | 185 ;; message when an already defined advised function gets redefined with a |
215 ;; new original definition and de/activated. | 186 ;; new original definition and de/activated. |
187 | |
188 ;; Look at the documentation of `ad-default-compilation-action' for possible | |
189 ;; values of this variable. Its default value is `maybe' which will compile | |
190 ;; advised definitions during activation in case the byte-compiler is already | |
191 ;; loaded. Otherwise, it will leave them uncompiled. | |
216 | 192 |
217 ;; @ Motivation: | 193 ;; @ Motivation: |
218 ;; ============= | 194 ;; ============= |
219 ;; Before I go on explaining how advice works, here are four simple examples | 195 ;; Before I go on explaining how advice works, here are four simple examples |
220 ;; how this package can be used. The first three are very useful, the last one | 196 ;; how this package can be used. The first three are very useful, the last one |
573 ;; redefined with the advised definition. This also means that undefined | 549 ;; redefined with the advised definition. This also means that undefined |
574 ;; functions cannot get activated even though they might be already advised. | 550 ;; functions cannot get activated even though they might be already advised. |
575 | 551 |
576 ;; The advised definition will get compiled either if `ad-activate' was called | 552 ;; The advised definition will get compiled either if `ad-activate' was called |
577 ;; interactively with a prefix argument, or called explicitly with its second | 553 ;; interactively with a prefix argument, or called explicitly with its second |
578 ;; argument as t, or, if this was a case of forward advice if the original | 554 ;; argument as t, or, if `ad-default-compilation-action' justifies it according |
579 ;; definition of the function was compiled. If the advised definition was | 555 ;; to the current system state. If the advised definition was |
580 ;; constructed during "preactivation" (see below) then that definition will | 556 ;; constructed during "preactivation" (see below) then that definition will |
581 ;; be already compiled because it was constructed during byte-compilation of | 557 ;; be already compiled because it was constructed during byte-compilation of |
582 ;; the file that contained the `defadvice' with the `preactivate' flag. | 558 ;; the file that contained the `defadvice' with the `preactivate' flag. |
583 | 559 |
584 ;; `ad-deactivate' can be used to back-define an advised function to its | 560 ;; `ad-deactivate' can be used to back-define an advised function to its |
689 | 665 |
690 ;; A certain piece of advice is considered a match if its name contains a | 666 ;; A certain piece of advice is considered a match if its name contains a |
691 ;; match for the regular expression. To enable ange-ftp again we would use | 667 ;; match for the regular expression. To enable ange-ftp again we would use |
692 ;; `ad-enable-regexp' and then activate or update again. | 668 ;; `ad-enable-regexp' and then activate or update again. |
693 | 669 |
694 ;; @@ Forward advice, function definition hooks: | 670 ;; @@ Forward advice, automatic advice activation: |
695 ;; ============================================= | 671 ;; =============================================== |
696 ;; Because most Emacs Lisp packages are loaded on demand via an autoload | 672 ;; Because most Emacs Lisp packages are loaded on demand via an autoload |
697 ;; mechanism it is essential to be able to "forward advise" functions. | 673 ;; mechanism it is essential to be able to "forward advise" functions. |
698 ;; Otherwise, proper advice definition and activation would make it necessary | 674 ;; Otherwise, proper advice definition and activation would make it necessary |
699 ;; to preload every file that defines a certain function before it can be | 675 ;; to preload every file that defines a certain function before it can be |
700 ;; advised, which would partly defeat the purpose of the advice mechanism. | 676 ;; advised, which would partly defeat the purpose of the advice mechanism. |
704 ;; information for a possibly undefined function. | 680 ;; information for a possibly undefined function. |
705 | 681 |
706 ;; Advice implements forward advice mainly via the following: 1) Separation | 682 ;; Advice implements forward advice mainly via the following: 1) Separation |
707 ;; of advice definition and activation that makes it possible to accumulate | 683 ;; of advice definition and activation that makes it possible to accumulate |
708 ;; advice information without having the original function already defined, | 684 ;; advice information without having the original function already defined, |
709 ;; 2) special versions of the function defining functions `defun', `defmacro' | 685 ;; 2) special versions of the built-in functions `fset/defalias' which check |
710 ;; and `fset' that check for advice information whenever they define a | 686 ;; for advice information whenever they define a function. If advice |
711 ;; function. If advice information was found and forward advice is enabled | 687 ;; information was found then the advice will immediately get activated when |
712 ;; then the advice will immediately get activated when the function gets | 688 ;; the function gets defined. |
713 ;; defined. | 689 |
714 | 690 ;; Automatic advice activation means, that whenever a function gets defined |
715 ;; @@@ Enabling forward advice: | |
716 ;; ============================ | |
717 ;; Forward advice is enabled by setting `ad-activate-on-definition' to t | |
718 ;; and then calling `ad-start-advice' which can either be done interactively, | |
719 ;; directly with `(ad-start-advice)' in your .emacs, or by setting | |
720 ;; `ad-start-advice-on-load' to t before advice gets loaded. For example, | |
721 ;; putting the following into your .emacs will enable forward advice: | |
722 ;; | |
723 ;; (setq ad-start-advice-on-load t) | |
724 ;; (setq ad-activate-on-definition t) | |
725 ;; | |
726 ;; "Activation on definition" means, that whenever a function gets defined | |
727 ;; with either `defun', `defmacro', `fset' or by loading a byte-compiled | 691 ;; with either `defun', `defmacro', `fset' or by loading a byte-compiled |
728 ;; file, and the function has some advice-info stored with it then that | 692 ;; file, and the function has some advice-info stored with it then that |
729 ;; advice will get activated right away. | 693 ;; advice will get activated right away. |
730 | 694 |
731 ;; If jwz's byte-compiler is used then `ad-use-jwz-byte-compiler' should | 695 ;; @@@ Enabling automatic advice activation: |
732 ;; be t in order to make forward advice work with functions defined in | 696 ;; ========================================= |
733 ;; compiled files generated by that compiler. In v19s which use this | 697 ;; Automatic advice activation is enabled by default. It can be disabled by |
734 ;; compiler the value of this variable will be correct automatically. | 698 ;; doint `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'. |
735 ;; If you use a v18 Emacs in conjunction with jwz's compiler and you want | |
736 ;; to use forward advice then you should check its value after loading | |
737 ;; advice. If it is nil set it explicitly with | |
738 ;; | |
739 ;; (setq ad-use-jwz-byte-compiler t) | |
740 ;; | |
741 ;; along with `ad-activate-on-definition' before you start advice (see above). | |
742 | |
743 ;; IMPORTANT: A v18 Emacs + jwz's compiler + forward advice means performance | |
744 ;; tradeoffs which are described below. | |
745 | |
746 ;; @@@ Forward advice with compiled files generated by jwz's byte-compiler: | |
747 ;; ======================================================================== | |
748 ;; The v18 byte-compiler only uses `defun/defmacro' to define compiled | |
749 ;; functions, hence, providing advised versions of these functions was | |
750 ;; sufficient to achieve forward advice. With the advent of Jamie Zawinski's | |
751 ;; optimizing byte-compiler which is now standardly used in Emacs-19 and | |
752 ;; Lemacs things became more complicated. jwz's compiler defines functions | |
753 ;; in hunks of byte-code without explicit usage of `defun/defmacro'. To | |
754 ;; still provide forward advice even in this scenario, advice defines an | |
755 ;; advised version of the `byte-code' subr that scans its arguments for | |
756 ;; function definitions during the loading of compiled files. While this is | |
757 ;; no problem in a v19 Emacs, because it uses a new datatype for compiled | |
758 ;; code objects and the `byte-code' subr is only rarely used at all, it | |
759 ;; presents a major problem in a v18 Emacs because there calls to | |
760 ;; `byte-code' are the only means of executing compiled code (every body of | |
761 ;; a compiled function contains a call to `byte-code'). Because the advised | |
762 ;; `byte-code' has to perform some extra checks every call to a compiled | |
763 ;; function becomes more expensive. | |
764 | |
765 ;; Enabling forward advice leads to performance degradation in the following | |
766 ;; situations: | |
767 ;; - A v18 Emacs is used and the value of `ad-use-jwz-byte-compiler' is t | |
768 ;; (either because jwz's byte-compiler is used instead of the standard v18 | |
769 ;; compiler, or some compiled files generated by jwz's compiler are used). | |
770 ;; - A v19 Emacs is used with some old-style v18 compiled files. | |
771 ;; Some performance experiments I conducted showed that function call intensive | |
772 ;; code (such as the highly recursive byte-compiler itself) slows down by a | |
773 ;; factor of 1.8. Function call intensive code that runs while a file gets | |
774 ;; loaded can slow down by a factor of 6! For the v19 scenario this performance | |
775 ;; lossage would only apply to code that was loaded from old v18 compiled | |
776 ;; files. | |
777 | |
778 ;; MORAL: If you use a v18 Emacs in conjunction with jwz's byte-compiler you | |
779 ;; should think twice whether you really need forward advice. There are some | |
780 ;; alternatives to forward advice described below that might give you what | |
781 ;; you need without the loss of performance (that performance loss probably | |
782 ;; outweighs by far any performance gain due to the optimizing nature of jwz's | |
783 ;; compiler). | |
784 | |
785 ;; @@@ Alternatives to automatic activation of forward advice: | |
786 ;; =========================================================== | |
787 ;; If you use a v18 Emacs in conjunction with jwz's compiler, or you simply | |
788 ;; don't trust the automatic activation mechanism of forward advice, then | |
789 ;; you can use some of the following alternatives to get around that: | |
790 ;; - Preload the file that contains the definition of the function that you | |
791 ;; want to advice. Inelegant and wasteful, but it works. | |
792 ;; - If the package that contains the definition of the function you want to | |
793 ;; advise has any mode hooks, and the advised function is only used once such | |
794 ;; a mode has been entered, then you can activate the advice in the mode | |
795 ;; hook. Just put a form like `(ad-activate 'my-advised-fn t)' into the | |
796 ;; hook definition. The caching mechanism will reuse advised definitions, | |
797 ;; so calling that mode hook over and over again will not construct | |
798 ;; advised definitions over and over again, so you won't loose any | |
799 ;; performance. | |
800 ;; - If your Emacs comes with file load hooks (such as v19's | |
801 ;; `after-load-alist' mechanism), then you can put the activation form | |
802 ;; into that, for example, add `("myfile" (ad-activate 'my-advised-fn t))' | |
803 ;; to it to activate the advice right ater "myfile" got loaded. | |
804 | |
805 ;; @@@ Function definition hooks: | |
806 ;; ============================== | |
807 ;; Automatic activation of forward advice is implemented as an application | |
808 ;; of a more general function definition hook mechanism. After a function | |
809 ;; gets re/defined with `defun/defmacro/fset' or via a hunk of byte-code | |
810 ;; during the loading of a byte-compiled file, and function definition hooks | |
811 ;; are enabled, then all hook functions stored in `ad-definition-hooks' are | |
812 ;; run with the variable `ad-defined-function' bound to the name of the | |
813 ;; currently defined function. | |
814 | |
815 ;; Function definition hooks can be enabled with | |
816 ;; | |
817 ;; (setq ad-enable-definition-hooks t) | |
818 ;; | |
819 ;; before advice gets started with `ad-start-advice'. Setting | |
820 ;; `ad-activate-on-definition' to t automatically enables definition hooks | |
821 ;; regardless of the value of `ad-enable-definition-hooks'. | |
822 | |
823 ;; @@@ Wish list: | |
824 ;; ============== | |
825 ;; - The implementation of definition hooks for v19 compiled files would be | |
826 ;; safer if jwz's byte-compiler used something like `byte-code-tl' instead | |
827 ;; of `byte-code' to execute hunks of function defining byte-code at the | |
828 ;; top level of compiled files. | |
829 ;; - Definition hooks should be implemented directly as part of the C-code | |
830 ;; that implements `fset', because then Advice wouldn't have to use all | |
831 ;; these dirty hacks to achieve this functionality. | |
832 | 699 |
833 ;; @@ Caching of advised definitions: | 700 ;; @@ Caching of advised definitions: |
834 ;; ================================== | 701 ;; ================================== |
835 ;; After an advised definition got constructed it gets cached as part of the | 702 ;; After an advised definition got constructed it gets cached as part of the |
836 ;; advised function's advice-info so it can be reused, for example, after an | 703 ;; advised function's advice-info so it can be reused, for example, after an |
1952 (provide 'advice-preload) | 1819 (provide 'advice-preload) |
1953 ;; During a normal load this is a noop: | 1820 ;; During a normal load this is a noop: |
1954 (require 'advice-preload "advice.el") | 1821 (require 'advice-preload "advice.el") |
1955 | 1822 |
1956 | 1823 |
1957 ;; @@ Variable definitions: | |
1958 ;; ======================== | |
1959 | |
1960 (defconst ad-version "2.11") | |
1961 | |
1962 (defmacro ad-lemacs-p () | 1824 (defmacro ad-lemacs-p () |
1963 ;;Expands into Non-nil constant if we run Lucid's version of Emacs-19. | 1825 ;;Expands into Non-nil constant if we run Lucid's version of Emacs-19. |
1964 ;;Unselected conditional code will be optimized away during compilation. | 1826 ;;Unselected conditional code will be optimized away during compilation. |
1965 (string-match "Lucid" emacs-version)) | 1827 (string-match "Lucid" emacs-version)) |
1966 | 1828 |
1967 ;;;###autoload | 1829 |
1968 (defvar ad-start-advice-on-load t | 1830 ;; @@ Variable definitions: |
1969 "*Non-nil will start Advice magic when this file gets loaded. | 1831 ;; ======================== |
1970 Also see function `ad-start-advice'.") | 1832 |
1971 | 1833 (defconst ad-version "2.13") |
1972 ;;;###autoload | |
1973 (defvar ad-activate-on-definition nil | |
1974 "*Non-nil means automatic advice activation at function definition. | |
1975 Set this variable to t if you want to enable forward advice (which is | |
1976 automatic advice activation of a previously undefined function at the | |
1977 point the function gets defined/loaded/autoloaded). The value of this | |
1978 variable takes effect only during the execution of `ad-start-advice'. | |
1979 If non-nil it will enable definition hooks regardless of the value | |
1980 of `ad-enable-definition-hooks'.") | |
1981 | 1834 |
1982 ;;;###autoload | 1835 ;;;###autoload |
1983 (defvar ad-redefinition-action 'warn | 1836 (defvar ad-redefinition-action 'warn |
1984 "*Defines what to do with redefinitions during de/activation. | 1837 "*Defines what to do with redefinitions during Advice de/activation. |
1985 Redefinition occurs if a previously activated function that already has an | 1838 Redefinition occurs if a previously activated function that already has an |
1986 original definition associated with it gets redefined and then de/activated. | 1839 original definition associated with it gets redefined and then de/activated. |
1987 In such a case we can either accept the current definition as the new | 1840 In such a case we can either accept the current definition as the new |
1988 original definition, discard the current definition and replace it with the | 1841 original definition, discard the current definition and replace it with the |
1989 old original, or keep it and raise an error. The values `accept', `discard', | 1842 old original, or keep it and raise an error. The values `accept', `discard', |
1990 `error' or `warn' govern what will be done. `warn' is just like `accept' but | 1843 `error' or `warn' govern what will be done. `warn' is just like `accept' but |
1991 it additionally prints a warning message. All other values will be | 1844 it additionally prints a warning message. All other values will be |
1992 interpreted as `error'.") | 1845 interpreted as `error'.") |
1993 | 1846 |
1994 ;;;###autoload | 1847 ;;;###autoload |
1995 (defvar ad-definition-hooks nil | 1848 (defvar ad-default-compilation-action 'maybe |
1996 "*List of hooks to be run after a function definition. | 1849 "*Defines whether to compile advised definitions during activation. |
1997 The variable `ad-defined-function' will be bound to the name of | 1850 A value of `always' will result in unconditional compilation, `never' will |
1998 the currently defined function when the hook function is run.") | 1851 always avoid compilation, `maybe' will compile if the byte-compiler is already |
1999 | 1852 loaded, and `like-original' will compile if the original definition of the |
2000 ;;;###autoload | 1853 advised function is compiled or a built-in function. Every other value will |
2001 (defvar ad-enable-definition-hooks nil | 1854 be interpreted as `maybe'. This variable will only be considered if the |
2002 "*Non-nil will enable hooks to be run on function definition. | 1855 COMPILE argument of `ad-activate' was supplied as nil.") |
2003 Setting this variable is a noop unless the value of | |
2004 `ad-activate-on-definition' (which see) is nil.") | |
2005 | 1856 |
2006 | 1857 |
2007 ;; @@ Some utilities: | 1858 ;; @@ Some utilities: |
2008 ;; ================== | 1859 ;; ================== |
2009 | 1860 |
2098 (defun ad-save-real-definitions () | 1949 (defun ad-save-real-definitions () |
2099 ;; Macro expansion will hardcode the values of the various byte-compiler | 1950 ;; Macro expansion will hardcode the values of the various byte-compiler |
2100 ;; properties into the compiled version of this function such that the | 1951 ;; properties into the compiled version of this function such that the |
2101 ;; proper values will be available at runtime without loading the compiler: | 1952 ;; proper values will be available at runtime without loading the compiler: |
2102 (ad-save-real-definition fset) | 1953 (ad-save-real-definition fset) |
2103 (ad-save-real-definition documentation) | 1954 (ad-save-real-definition documentation)) |
2104 (ad-save-real-definition byte-code) | |
2105 (put 'ad-real-byte-code 'byte-compile nil)) | |
2106 | 1955 |
2107 (ad-save-real-definitions) | 1956 (ad-save-real-definitions) |
2108 | 1957 |
2109 | 1958 |
2110 ;; @@ Advice info access fns: | 1959 ;; @@ Advice info access fns: |
2261 (if (ad-advice-enabled advice) | 2110 (if (ad-advice-enabled advice) |
2262 (setq enabled-advices (cons advice enabled-advices)))) | 2111 (setq enabled-advices (cons advice enabled-advices)))) |
2263 (reverse enabled-advices))) | 2112 (reverse enabled-advices))) |
2264 | 2113 |
2265 | 2114 |
2115 ;; @@ Dealing with automatic advice activation via `fset/defalias': | |
2116 ;; ================================================================ | |
2117 | |
2118 ;; Since Emacs 19.26 the built-in versions of `fset' and `defalias' | |
2119 ;; take care of automatic advice activation, hence, we don't have to | |
2120 ;; hack it anymore by advising `fset/defun/defmacro/byte-code/etc'. | |
2121 | |
2122 ;; The functionality of the new `fset' is as follows: | |
2123 ;; | |
2124 ;; fset(sym,newdef) | |
2125 ;; assign NEWDEF to SYM | |
2126 ;; if (get SYM 'ad-advice-info) | |
2127 ;; ad-activate(SYM, nil) | |
2128 ;; return (symbol-function SYM) | |
2129 ;; | |
2130 ;; Whether advised definitions created by automatic activations will be | |
2131 ;; compiled depends on the value of `ad-default-compilation-action'. | |
2132 | |
2133 ;; Since calling `ad-activate' in the built-in definition of `fset' can | |
2134 ;; create major disasters we have to be a bit careful. One precaution is | |
2135 ;; to provide a dummy definition for `ad-activate' which can be used to | |
2136 ;; turn off automatic advice activation (e.g., when `ad-stop-advice' or | |
2137 ;; `ad-recover-normality' are called). Another is to avoid recursive calls | |
2138 ;; to `ad-activate-on' by using `ad-with-auto-activation-disabled' where | |
2139 ;; appropriate, especially in a safe version of `fset'. | |
2140 | |
2141 ;; For now define `ad-activate' to the dummy definition: | |
2142 (defun ad-activate (function &optional compile) | |
2143 "Automatic advice activation is disabled. `ad-start-advice' enables it." | |
2144 nil) | |
2145 | |
2146 ;; This is just a copy of the above: | |
2147 (defun ad-activate-off (function &optional compile) | |
2148 "Automatic advice activation is disabled. `ad-start-advice' enables it." | |
2149 nil) | |
2150 | |
2151 ;; This will be t for top-level calls to `ad-activate-on': | |
2152 (defvar ad-activate-on-top-level t) | |
2153 | |
2154 (defmacro ad-with-auto-activation-disabled (&rest body) | |
2155 (` (let ((ad-activate-on-top-level nil)) | |
2156 (,@ body)))) | |
2157 | |
2158 (defun ad-safe-fset (symbol definition) | |
2159 ;; A safe `fset' which will never call `ad-activate' recursively. | |
2160 (ad-with-auto-activation-disabled | |
2161 (ad-real-fset symbol definition))) | |
2162 | |
2163 | |
2266 ;; @@ Access functions for original definitions: | 2164 ;; @@ Access functions for original definitions: |
2267 ;; ============================================ | 2165 ;; ============================================ |
2268 ;; The advice-info of an advised function contains its `origname' which is | 2166 ;; The advice-info of an advised function contains its `origname' which is |
2269 ;; a symbol that is fbound to the original definition available at the first | 2167 ;; a symbol that is fbound to the original definition available at the first |
2270 ;; proper activation of the function after a legal re/definition. If the | 2168 ;; proper activation of the function after a legal re/definition. If the |
2280 (` (let ((origname (ad-get-advice-info-field (, function) 'origname))) | 2178 (` (let ((origname (ad-get-advice-info-field (, function) 'origname))) |
2281 (if (fboundp origname) | 2179 (if (fboundp origname) |
2282 (symbol-function origname))))) | 2180 (symbol-function origname))))) |
2283 | 2181 |
2284 (defmacro ad-set-orig-definition (function definition) | 2182 (defmacro ad-set-orig-definition (function definition) |
2285 (` (ad-real-fset | 2183 (` (ad-safe-fset |
2286 (ad-get-advice-info-field function 'origname) (, definition)))) | 2184 (ad-get-advice-info-field function 'origname) (, definition)))) |
2287 | 2185 |
2288 (defmacro ad-clear-orig-definition (function) | 2186 (defmacro ad-clear-orig-definition (function) |
2289 (` (fmakunbound (ad-get-advice-info-field (, function) 'origname)))) | 2187 (` (fmakunbound (ad-get-advice-info-field (, function) 'origname)))) |
2290 | 2188 |
2596 | 2494 |
2597 ;; Emacs/Lemacs cross-compatibility | 2495 ;; Emacs/Lemacs cross-compatibility |
2598 ;; (compiled-function-p is an obsolete function in Emacs): | 2496 ;; (compiled-function-p is an obsolete function in Emacs): |
2599 (if (and (not (fboundp 'byte-code-function-p)) | 2497 (if (and (not (fboundp 'byte-code-function-p)) |
2600 (fboundp 'compiled-function-p)) | 2498 (fboundp 'compiled-function-p)) |
2601 (ad-real-fset 'byte-code-function-p 'compiled-function-p)) | 2499 (ad-safe-fset 'byte-code-function-p 'compiled-function-p)) |
2602 | 2500 |
2603 (defmacro ad-compiled-p (definition) | 2501 (defmacro ad-compiled-p (definition) |
2604 ;;"non-nil if DEFINITION is a compiled byte-code object." | 2502 ;;"non-nil if DEFINITION is a compiled byte-code object." |
2605 (` (or (byte-code-function-p (, definition)) | 2503 (` (or (byte-code-function-p (, definition)) |
2606 (and (ad-macro-p (, definition)) | 2504 (and (ad-macro-p (, definition)) |
2775 | 2673 |
2776 (defun ad-compile-function (function) | 2674 (defun ad-compile-function (function) |
2777 "Byte-compiles FUNCTION (or macro) if it is not yet compiled." | 2675 "Byte-compiles FUNCTION (or macro) if it is not yet compiled." |
2778 (interactive "aByte-compile function: ") | 2676 (interactive "aByte-compile function: ") |
2779 (if (ad-is-compilable function) | 2677 (if (ad-is-compilable function) |
2780 (byte-compile function))) | 2678 ;; Need to turn off auto-activation |
2679 ;; because `byte-compile' uses `fset': | |
2680 (ad-with-auto-activation-disabled | |
2681 (byte-compile function)))) | |
2781 | 2682 |
2782 | 2683 |
2783 ;; @@ Constructing advised definitions: | 2684 ;; @@ Constructing advised definitions: |
2784 ;; ==================================== | 2685 ;; ==================================== |
2785 ;; | 2686 ;; |
3467 (unwind-protect | 3368 (unwind-protect |
3468 (progn | 3369 (progn |
3469 (ad-add-advice function advice class position) | 3370 (ad-add-advice function advice class position) |
3470 (ad-enable-advice function class (ad-advice-name advice)) | 3371 (ad-enable-advice function class (ad-advice-name advice)) |
3471 (ad-clear-cache function) | 3372 (ad-clear-cache function) |
3472 (ad-activate function nil) | 3373 (ad-activate-on function -1) |
3473 (if (and (ad-is-active function) | 3374 (if (and (ad-is-active function) |
3474 (ad-get-cache-definition function)) | 3375 (ad-get-cache-definition function)) |
3475 (list (ad-get-cache-definition function) | 3376 (list (ad-get-cache-definition function) |
3476 (ad-get-cache-id function)))) | 3377 (ad-get-cache-id function)))) |
3477 (ad-set-advice-info function old-advice-info) | 3378 (ad-set-advice-info function old-advice-info) |
3478 ;; Don't `fset' function to nil if it was previously unbound: | 3379 ;; Don't `fset' function to nil if it was previously unbound: |
3479 (if function-defined-p | 3380 (if function-defined-p |
3480 (ad-real-fset function old-definition) | 3381 (ad-safe-fset function old-definition) |
3481 (fmakunbound function))))) | 3382 (fmakunbound function))))) |
3383 | |
3384 | |
3385 ;; @@ Freezing: | |
3386 ;; ============ | |
3387 ;; Freezing transforms a `defadvice' into a redefining `defun/defmacro' | |
3388 ;; for the advised function without keeping any advice information. This | |
3389 ;; feature was jwz's idea: It generates a dumpable function definition | |
3390 ;; whose documentation can be written to the DOC file, and the generated | |
3391 ;; code does not need any Advice runtime support. Of course, frozen advices | |
3392 ;; cannot be undone. | |
3393 | |
3394 ;; Freezing only considers the advice of the particular `defadvice', other | |
3395 ;; already existing advices for the same function will be ignored. To ensure | |
3396 ;; proper interaction when an already advised function gets redefined with | |
3397 ;; a frozen advice, frozen advices always use the actual original definition | |
3398 ;; of the function, i.e., they are always at the core of the onion. E.g., if | |
3399 ;; an already advised function gets redefined with a frozen advice and then | |
3400 ;; unadvised, the frozen advice remains as the new definition of the function. | |
3401 | |
3402 ;; While multiple freeze advices for a single function or freeze-advising | |
3403 ;; of an already advised function are possible, they are better avoided, | |
3404 ;; because definition/compile/load ordering is relevant, and it becomes | |
3405 ;; incomprehensible pretty quickly. | |
3406 | |
3407 (defun ad-make-freeze-definition (function advice class position) | |
3408 (if (not (ad-has-proper-definition function)) | |
3409 (error | |
3410 "ad-make-freeze-definition: `%s' is not yet defined" | |
3411 function)) | |
3412 (let* ((name (ad-advice-name advice)) | |
3413 ;; With a unique origname we can have multiple freeze advices | |
3414 ;; for the same function, each overloading the previous one: | |
3415 (unique-origname | |
3416 (intern (format "%s-%s-%s" (ad-make-origname function) class name))) | |
3417 (orig-definition | |
3418 ;; If FUNCTION is already advised, we'll use its current origdef | |
3419 ;; as the original definition of the frozen advice: | |
3420 (or (ad-get-orig-definition function) | |
3421 (symbol-function function))) | |
3422 (old-advice-info | |
3423 (if (ad-is-advised function) | |
3424 (ad-copy-advice-info function))) | |
3425 (real-docstring-fn | |
3426 (symbol-function 'ad-make-advised-definition-docstring)) | |
3427 (real-origname-fn | |
3428 (symbol-function 'ad-make-origname)) | |
3429 (frozen-definition | |
3430 (unwind-protect | |
3431 (progn | |
3432 ;; Make sure we construct a proper docstring: | |
3433 (ad-safe-fset 'ad-make-advised-definition-docstring | |
3434 'ad-make-freeze-docstring) | |
3435 ;; Make sure `unique-origname' is used as the origname: | |
3436 (ad-safe-fset 'ad-make-origname '(lambda (x) unique-origname)) | |
3437 ;; No we reset all current advice information to nil and | |
3438 ;; generate an advised definition that's solely determined | |
3439 ;; by ADVICE and the current origdef of FUNCTION: | |
3440 (ad-set-advice-info function nil) | |
3441 (ad-add-advice function advice class position) | |
3442 ;; The following will provide proper real docstrings as | |
3443 ;; well as a definition that will make the compiler happy: | |
3444 (ad-set-orig-definition function orig-definition) | |
3445 (ad-make-advised-definition function)) | |
3446 ;; Restore the old advice state: | |
3447 (ad-set-advice-info function old-advice-info) | |
3448 ;; Restore functions: | |
3449 (ad-safe-fset | |
3450 'ad-make-advised-definition-docstring real-docstring-fn) | |
3451 (ad-safe-fset 'ad-make-origname real-origname-fn)))) | |
3452 (if frozen-definition | |
3453 (let* ((macro-p (ad-macro-p frozen-definition)) | |
3454 (body (cdr (if macro-p | |
3455 (ad-lambdafy frozen-definition) | |
3456 frozen-definition)))) | |
3457 (` (progn | |
3458 (if (not (fboundp '(, unique-origname))) | |
3459 (fset '(, unique-origname) | |
3460 ;; avoid infinite recursion in case the function | |
3461 ;; we want to freeze is already advised: | |
3462 (or (ad-get-orig-definition '(, function)) | |
3463 (symbol-function '(, function))))) | |
3464 ((, (if macro-p 'defmacro 'defun)) | |
3465 (, function) | |
3466 (,@ body)))))))) | |
3467 | |
3468 | |
3469 ;; @@ Activation and definition handling: | |
3470 ;; ====================================== | |
3471 | |
3472 (defun ad-should-compile (function compile) | |
3473 ;;"Returns non-nil if the advised FUNCTION should be compiled. | |
3474 ;;If COMPILE is non-nil and not a negative number then it returns t. | |
3475 ;;If COMPILE is a negative number then it returns nil. | |
3476 ;;If COMPILE is nil then the result depends on the value of | |
3477 ;;`ad-default-compilation-action' (which see)." | |
3478 (if (integerp compile) | |
3479 (>= compile 0) | |
3480 (if compile | |
3481 compile | |
3482 (cond ((eq ad-default-compilation-action 'never) | |
3483 nil) | |
3484 ((eq ad-default-compilation-action 'always) | |
3485 t) | |
3486 ((eq ad-default-compilation-action 'like-original) | |
3487 (or (ad-subr-p (ad-get-orig-definition function)) | |
3488 (ad-compiled-p (ad-get-orig-definition function)))) | |
3489 ;; everything else means `maybe': | |
3490 (t (featurep 'byte-compile)))))) | |
3482 | 3491 |
3483 (defun ad-activate-advised-definition (function compile) | 3492 (defun ad-activate-advised-definition (function compile) |
3484 ;;"Redefines FUNCTION with its advised definition from cache or scratch. | 3493 ;;"Redefines FUNCTION with its advised definition from cache or scratch. |
3485 ;;If COMPILE is true the resulting FUNCTION will be compiled. The current | 3494 ;;The resulting FUNCTION will be compiled if `ad-should-compile' returns t. |
3486 ;;definition and its cache-id will be put into the cache." | 3495 ;;The current definition and its cache-id will be put into the cache." |
3487 (let ((verified-cached-definition | 3496 (let ((verified-cached-definition |
3488 (if (ad-verify-cache-id function) | 3497 (if (ad-verify-cache-id function) |
3489 (ad-get-cache-definition function)))) | 3498 (ad-get-cache-definition function)))) |
3490 (ad-real-fset function | 3499 (ad-safe-fset function |
3491 (or verified-cached-definition | 3500 (or verified-cached-definition |
3492 (ad-make-advised-definition function))) | 3501 (ad-make-advised-definition function))) |
3493 (if compile (ad-compile-function function)) | 3502 (if (ad-should-compile function compile) |
3503 (ad-compile-function function)) | |
3494 (if verified-cached-definition | 3504 (if verified-cached-definition |
3495 (if (not (eq verified-cached-definition (symbol-function function))) | 3505 (if (not (eq verified-cached-definition (symbol-function function))) |
3496 ;; we must have compiled, cache the compiled definition: | 3506 ;; we must have compiled, cache the compiled definition: |
3497 (ad-set-cache | 3507 (ad-set-cache |
3498 function (symbol-function function) (ad-get-cache-id function))) | 3508 function (symbol-function function) (ad-get-cache-id function))) |
3526 ;; we have a redefinition: | 3536 ;; we have a redefinition: |
3527 (if (not (memq ad-redefinition-action '(accept discard warn))) | 3537 (if (not (memq ad-redefinition-action '(accept discard warn))) |
3528 (error "ad-handle-definition (see its doc): `%s' %s" | 3538 (error "ad-handle-definition (see its doc): `%s' %s" |
3529 function "illegally redefined") | 3539 function "illegally redefined") |
3530 (if (eq ad-redefinition-action 'discard) | 3540 (if (eq ad-redefinition-action 'discard) |
3531 (ad-real-fset function original-definition) | 3541 (ad-safe-fset function original-definition) |
3532 (ad-set-orig-definition function current-definition) | 3542 (ad-set-orig-definition function current-definition) |
3533 (if (eq ad-redefinition-action 'warn) | 3543 (if (eq ad-redefinition-action 'warn) |
3534 (message "ad-handle-definition: `%s' got redefined" | 3544 (message "ad-handle-definition: `%s' got redefined" |
3535 function)))) | 3545 function)))) |
3536 ;; either advised def or correct original is in place: | 3546 ;; either advised def or correct original is in place: |
3545 | 3555 |
3546 | 3556 |
3547 ;; @@ The top-level advice interface: | 3557 ;; @@ The top-level advice interface: |
3548 ;; ================================== | 3558 ;; ================================== |
3549 | 3559 |
3550 (defun ad-activate (function &optional compile) | 3560 (defun ad-activate-on (function &optional compile) |
3551 "Activates all the advice information of an advised FUNCTION. | 3561 "Activates all the advice information of an advised FUNCTION. |
3552 If FUNCTION has a proper original definition then an advised | 3562 If FUNCTION has a proper original definition then an advised |
3553 definition will be generated from FUNCTION's advice info and the | 3563 definition will be generated from FUNCTION's advice info and the |
3554 definition of FUNCTION will be replaced with it. If a previously | 3564 definition of FUNCTION will be replaced with it. If a previously |
3555 cached advised definition was available, it will be used. With an | 3565 cached advised definition was available, it will be used. |
3556 argument (COMPILE is non-nil) the resulting function (or a compilable | 3566 The optional COMPILE argument determines whether the resulting function |
3557 cached definition) will also be compiled. Activation of an advised | 3567 or a compilable cached definition will be compiled. If it is negative |
3558 function that has an advice info but no actual pieces of advice is | 3568 no compilation will be performed, if it is positive or otherwise non-nil |
3559 equivalent to a call to `ad-unadvise'. Activation of an advised | 3569 the resulting function will be compiled, if it is nil the behavior depends |
3560 function that has actual pieces of advice but none of them are enabled | 3570 on the value of `ad-default-compilation-action' (which see). |
3561 is equivalent to a call to `ad-deactivate'. The current advised | 3571 Activation of an advised function that has an advice info but no actual |
3572 pieces of advice is equivalent to a call to `ad-unadvise'. Activation of | |
3573 an advised function that has actual pieces of advice but none of them are | |
3574 enabled is equivalent to a call to `ad-deactivate'. The current advised | |
3562 definition will always be cached for later usage." | 3575 definition will always be cached for later usage." |
3563 (interactive | 3576 (interactive |
3564 (list (ad-read-advised-function "Activate advice of: ") | 3577 (list (ad-read-advised-function "Activate advice of: ") |
3565 current-prefix-arg)) | 3578 current-prefix-arg)) |
3566 (if (not (ad-is-advised function)) | 3579 (if ad-activate-on-top-level |
3567 (error "ad-activate: `%s' is not advised" function) | 3580 ;; avoid recursive calls to `ad-activate-on': |
3568 (ad-handle-definition function) | 3581 (ad-with-auto-activation-disabled |
3569 ;; Just return for forward advised and not yet defined functions: | 3582 (if (not (ad-is-advised function)) |
3570 (if (ad-get-orig-definition function) | 3583 (error "ad-activate: `%s' is not advised" function) |
3571 (if (not (ad-has-any-advice function)) | 3584 (ad-handle-definition function) |
3572 (ad-unadvise function) | 3585 ;; Just return for forward advised and not yet defined functions: |
3573 ;; Otherwise activate the advice: | 3586 (if (ad-get-orig-definition function) |
3574 (cond ((ad-has-redefining-advice function) | 3587 (if (not (ad-has-any-advice function)) |
3575 (ad-activate-advised-definition function compile) | 3588 (ad-unadvise function) |
3576 (ad-set-advice-info-field function 'active t) | 3589 ;; Otherwise activate the advice: |
3577 (eval (ad-make-hook-form function 'activation)) | 3590 (cond ((ad-has-redefining-advice function) |
3578 function) | 3591 (ad-activate-advised-definition function compile) |
3579 ;; Here we are if we have all disabled advices: | 3592 (ad-set-advice-info-field function 'active t) |
3580 (t (ad-deactivate function))))))) | 3593 (eval (ad-make-hook-form function 'activation)) |
3594 function) | |
3595 ;; Here we are if we have all disabled advices: | |
3596 (t (ad-deactivate function))))))))) | |
3581 | 3597 |
3582 (defun ad-deactivate (function) | 3598 (defun ad-deactivate (function) |
3583 "Deactivates the advice of an actively advised FUNCTION. | 3599 "Deactivates the advice of an actively advised FUNCTION. |
3584 If FUNCTION has a proper original definition, then the current | 3600 If FUNCTION has a proper original definition, then the current |
3585 definition of FUNCTION will be replaced with it. All the advice | 3601 definition of FUNCTION will be replaced with it. All the advice |
3592 (cond ((ad-is-active function) | 3608 (cond ((ad-is-active function) |
3593 (ad-handle-definition function) | 3609 (ad-handle-definition function) |
3594 (if (not (ad-get-orig-definition function)) | 3610 (if (not (ad-get-orig-definition function)) |
3595 (error "ad-deactivate: `%s' has no original definition" | 3611 (error "ad-deactivate: `%s' has no original definition" |
3596 function) | 3612 function) |
3597 (ad-real-fset function (ad-get-orig-definition function)) | 3613 (ad-safe-fset function (ad-get-orig-definition function)) |
3598 (ad-set-advice-info-field function 'active nil) | 3614 (ad-set-advice-info-field function 'active nil) |
3599 (eval (ad-make-hook-form function 'deactivation)) | 3615 (eval (ad-make-hook-form function 'deactivation)) |
3600 function))))) | 3616 function))))) |
3601 | 3617 |
3602 (defun ad-update (function &optional compile) | 3618 (defun ad-update (function &optional compile) |
3603 "Update the advised definition of FUNCTION if its advice is active. | 3619 "Update the advised definition of FUNCTION if its advice is active. |
3604 With a prefix argument or if the current definition is compiled compile the | 3620 See `ad-activate-on' for documentation on the optional COMPILE argument." |
3605 resulting advised definition." | |
3606 (interactive | 3621 (interactive |
3607 (list (ad-read-advised-function | 3622 (list (ad-read-advised-function |
3608 "Update advised definition of: " 'ad-is-active))) | 3623 "Update advised definition of: " 'ad-is-active))) |
3609 (if (ad-is-active function) | 3624 (if (ad-is-active function) |
3610 (ad-activate | 3625 (ad-activate-on function compile))) |
3611 function (or compile (ad-compiled-p (symbol-function function)))))) | |
3612 | 3626 |
3613 (defun ad-unadvise (function) | 3627 (defun ad-unadvise (function) |
3614 "Deactivates FUNCTION and then removes all its advice information. | 3628 "Deactivates FUNCTION and then removes all its advice information. |
3615 If FUNCTION was not advised this will be a noop." | 3629 If FUNCTION was not advised this will be a noop." |
3616 (interactive | 3630 (interactive |
3632 (interactive | 3646 (interactive |
3633 (list (intern | 3647 (list (intern |
3634 (completing-read "Recover advised function: " obarray nil t)))) | 3648 (completing-read "Recover advised function: " obarray nil t)))) |
3635 (cond ((ad-is-advised function) | 3649 (cond ((ad-is-advised function) |
3636 (cond ((ad-get-orig-definition function) | 3650 (cond ((ad-get-orig-definition function) |
3637 (ad-real-fset function (ad-get-orig-definition function)) | 3651 (ad-safe-fset function (ad-get-orig-definition function)) |
3638 (ad-clear-orig-definition function))) | 3652 (ad-clear-orig-definition function))) |
3639 (ad-set-advice-info function nil) | 3653 (ad-set-advice-info function nil) |
3640 (ad-pop-advised-function function)))) | 3654 (ad-pop-advised-function function)))) |
3641 | 3655 |
3642 (defun ad-activate-regexp (regexp &optional compile) | 3656 (defun ad-activate-regexp (regexp &optional compile) |
3643 "Activates functions with an advice name containing a REGEXP match. | 3657 "Activates functions with an advice name containing a REGEXP match. |
3644 With prefix argument compiles resulting advised definitions." | 3658 See `ad-activate-on' for documentation on the optional COMPILE argument." |
3645 (interactive | 3659 (interactive |
3646 (list (ad-read-regexp "Activate via advice regexp: ") | 3660 (list (ad-read-regexp "Activate via advice regexp: ") |
3647 current-prefix-arg)) | 3661 current-prefix-arg)) |
3648 (ad-do-advised-functions (function) | 3662 (ad-do-advised-functions (function) |
3649 (if (ad-find-some-advice function 'any regexp) | 3663 (if (ad-find-some-advice function 'any regexp) |
3650 (ad-activate function compile)))) | 3664 (ad-activate-on function compile)))) |
3651 | 3665 |
3652 (defun ad-deactivate-regexp (regexp) | 3666 (defun ad-deactivate-regexp (regexp) |
3653 "Deactivates functions with an advice name containing REGEXP match." | 3667 "Deactivates functions with an advice name containing REGEXP match." |
3654 (interactive | 3668 (interactive |
3655 (list (ad-read-regexp "Deactivate via advice regexp: "))) | 3669 (list (ad-read-regexp "Deactivate via advice regexp: "))) |
3657 (if (ad-find-some-advice function 'any regexp) | 3671 (if (ad-find-some-advice function 'any regexp) |
3658 (ad-deactivate function)))) | 3672 (ad-deactivate function)))) |
3659 | 3673 |
3660 (defun ad-update-regexp (regexp &optional compile) | 3674 (defun ad-update-regexp (regexp &optional compile) |
3661 "Updates functions with an advice name containing a REGEXP match. | 3675 "Updates functions with an advice name containing a REGEXP match. |
3662 With prefix argument compiles resulting advised definitions." | 3676 See `ad-activate-on' for documentation on the optional COMPILE argument." |
3663 (interactive | 3677 (interactive |
3664 (list (ad-read-regexp "Update via advice regexp: ") | 3678 (list (ad-read-regexp "Update via advice regexp: ") |
3665 current-prefix-arg)) | 3679 current-prefix-arg)) |
3666 (ad-do-advised-functions (function) | 3680 (ad-do-advised-functions (function) |
3667 (if (ad-find-some-advice function 'any regexp) | 3681 (if (ad-find-some-advice function 'any regexp) |
3668 (ad-update function compile)))) | 3682 (ad-update function compile)))) |
3669 | 3683 |
3670 (defun ad-activate-all (&optional compile) | 3684 (defun ad-activate-all (&optional compile) |
3671 "Activates all currently advised functions. | 3685 "Activates all currently advised functions. |
3672 With prefix argument compiles resulting advised definitions." | 3686 See `ad-activate-on' for documentation on the optional COMPILE argument." |
3673 (interactive "P") | 3687 (interactive "P") |
3674 (ad-do-advised-functions (function) | 3688 (ad-do-advised-functions (function) |
3675 (ad-activate function))) | 3689 (ad-activate-on function compile))) |
3676 | 3690 |
3677 (defun ad-deactivate-all () | 3691 (defun ad-deactivate-all () |
3678 "Deactivates all currently advised functions." | 3692 "Deactivates all currently advised functions." |
3679 (interactive) | 3693 (interactive) |
3680 (ad-do-advised-functions (function) | 3694 (ad-do-advised-functions (function) |
3749 time. This generates a compiled advised definition according to the current | 3763 time. This generates a compiled advised definition according to the current |
3750 advice state that will be used during activation if appropriate. Only use | 3764 advice state that will be used during activation if appropriate. Only use |
3751 this if the `defadvice' gets actually compiled. | 3765 this if the `defadvice' gets actually compiled. |
3752 | 3766 |
3753 `freeze': Expands the `defadvice' into a redefining `defun/defmacro' according | 3767 `freeze': Expands the `defadvice' into a redefining `defun/defmacro' according |
3754 to the current advice state. No other advice information will be saved. | 3768 to this particular single advice. No other advice information will be saved. |
3755 Frozen advices cannot be undone, they behave like a hard redefinition of | 3769 Frozen advices cannot be undone, they behave like a hard redefinition of |
3756 the advised function. `freeze' implies `activate' and `preactivate'. The | 3770 the advised function. `freeze' implies `activate' and `preactivate'. The |
3757 documentation of the advised function can be dumped onto the `DOC' file | 3771 documentation of the advised function can be dumped onto the `DOC' file |
3758 during preloading. | 3772 during preloading. |
3759 | 3773 |
3789 name (memq 'protect flags) | 3803 name (memq 'protect flags) |
3790 (not (memq 'disable flags)) | 3804 (not (memq 'disable flags)) |
3791 (` (advice lambda (, arglist) (,@ body))))) | 3805 (` (advice lambda (, arglist) (,@ body))))) |
3792 (preactivation (if (memq 'preactivate flags) | 3806 (preactivation (if (memq 'preactivate flags) |
3793 (ad-preactivate-advice | 3807 (ad-preactivate-advice |
3794 function advice class position))) | 3808 function advice class position)))) |
3795 unique-origname | |
3796 (redefinition | |
3797 (if (memq 'freeze flags) | |
3798 (ad-with-originals (ad-make-advised-definition-docstring | |
3799 ad-make-origname) | |
3800 ;; Make sure we construct the actual docstring: | |
3801 (fset 'ad-make-advised-definition-docstring | |
3802 'ad-make-freeze-docstring) | |
3803 ;; With a unique origname we can have multiple freeze advices | |
3804 ;; for the same function, each overloading the previous one: | |
3805 (setq unique-origname | |
3806 (intern (format "%s-%s-%s" | |
3807 (ad-make-origname function) class name))) | |
3808 (fset 'ad-make-origname '(lambda (x) unique-origname)) | |
3809 (if (not (ad-has-proper-definition function)) | |
3810 (error | |
3811 "defadvice: `freeze' needs proper definition of `%s'" | |
3812 function)) | |
3813 (ad-preactivate-advice function advice class position))))) | |
3814 ;; Now for the things to be done at evaluation time: | 3809 ;; Now for the things to be done at evaluation time: |
3815 (if redefinition | 3810 (if (memq 'freeze flags) |
3816 ;; jwz's idea: Freeze the advised definition into a dumpable | 3811 ;; jwz's idea: Freeze the advised definition into a dumpable |
3817 ;; defun/defmacro whose docs can be written to the DOC file: | 3812 ;; defun/defmacro whose docs can be written to the DOC file: |
3818 (let* ((macro-p (ad-macro-p (car redefinition))) | 3813 (ad-make-freeze-definition function advice class position) |
3819 (body (cdr (if macro-p | |
3820 (ad-lambdafy (car redefinition)) | |
3821 (car redefinition))))) | |
3822 (` (progn | |
3823 (if (not (fboundp '(, unique-origname))) | |
3824 (fset '(, unique-origname) (symbol-function '(, function)))) | |
3825 ((, (if macro-p 'defmacro 'defun)) | |
3826 (, function) | |
3827 (,@ body))))) | |
3828 ;; the normal case: | 3814 ;; the normal case: |
3829 (` (progn | 3815 (` (progn |
3830 (ad-add-advice '(, function) '(, advice) '(, class) '(, position)) | 3816 (ad-add-advice '(, function) '(, advice) '(, class) '(, position)) |
3831 (,@ (if preactivation | 3817 (,@ (if preactivation |
3832 (` ((ad-set-cache | 3818 (` ((ad-set-cache |
3839 (car preactivation))))))) | 3825 (car preactivation))))))) |
3840 (t (` (function | 3826 (t (` (function |
3841 (, (car preactivation))))))) | 3827 (, (car preactivation))))))) |
3842 '(, (car (cdr preactivation)))))))) | 3828 '(, (car (cdr preactivation)))))))) |
3843 (,@ (if (memq 'activate flags) | 3829 (,@ (if (memq 'activate flags) |
3844 (` ((ad-activate '(, function) | 3830 (` ((ad-activate-on '(, function) |
3845 (, (if (memq 'compile flags) t))))))) | 3831 (, (if (memq 'compile flags) t))))))) |
3846 '(, function)))))) | 3832 '(, function)))))) |
3847 | 3833 |
3848 | 3834 |
3849 ;; @@ Tools: | 3835 ;; @@ Tools: |
3850 ;; ========= | 3836 ;; ========= |
3872 (setq index -1) | 3858 (setq index -1) |
3873 (mapcar | 3859 (mapcar |
3874 (function | 3860 (function |
3875 (lambda (function) | 3861 (lambda (function) |
3876 (setq index (1+ index)) | 3862 (setq index (1+ index)) |
3877 (` (ad-real-fset | 3863 (` (ad-safe-fset |
3878 '(, function) | 3864 '(, function) |
3879 (or (ad-get-orig-definition '(, function)) | 3865 (or (ad-get-orig-definition '(, function)) |
3880 (, (car (nth index current-bindings)))))))) | 3866 (, (car (nth index current-bindings)))))))) |
3881 functions))) | 3867 functions))) |
3882 (,@ body)) | 3868 (,@ body)) |
3886 (setq index -1) | 3872 (setq index -1) |
3887 (mapcar | 3873 (mapcar |
3888 (function | 3874 (function |
3889 (lambda (function) | 3875 (lambda (function) |
3890 (setq index (1+ index)) | 3876 (setq index (1+ index)) |
3891 (` (ad-real-fset | 3877 (` (ad-safe-fset |
3892 '(, function) | 3878 '(, function) |
3893 (, (car (nth index current-bindings))))))) | 3879 (, (car (nth index current-bindings))))))) |
3894 functions)))))))) | 3880 functions)))))))) |
3895 | 3881 |
3896 (if (not (get 'ad-with-originals 'lisp-indent-hook)) | 3882 (if (not (get 'ad-with-originals 'lisp-indent-hook)) |
3897 (put 'ad-with-originals 'lisp-indent-hook 1)) | 3883 (put 'ad-with-originals 'lisp-indent-hook 1)) |
3898 | 3884 |
3899 | 3885 |
3900 ;; @@ Advising `defun', `defmacro', `fset' and `documentation' | 3886 ;; @@ Advising `documentation': |
3901 ;; =========================================================== | 3887 ;; ============================ |
3902 ;; Use the advice mechanism to advise defun/defmacro/fset so we can forward | 3888 ;; Use the advice mechanism to advise `documentation' to make it |
3903 ;; advise functions that might be defined later during load/autoload. | 3889 ;; generate proper documentation strings for advised definitions: |
3904 ;; Enabling forward advice was the original motivation for doing this, it | |
3905 ;; has now been generalized to running definition hooks so other packages | |
3906 ;; can make use of this sort of functionality too. | |
3907 | |
3908 (defvar ad-defined-function nil) | |
3909 | |
3910 (defun ad-activate-defined-function (&optional function) | |
3911 "Activates the advice of an advised and defined FUNCTION. | |
3912 If the current definition of FUNCTION is byte-compiled then the advised | |
3913 definition will be compiled too. FUNCTION defaults to the value of | |
3914 `ad-defined-function'." | |
3915 (if (and (null function) | |
3916 ad-defined-function) | |
3917 (setq function ad-defined-function)) | |
3918 (if (and (ad-is-advised function) | |
3919 (ad-real-definition function)) | |
3920 (ad-activate function (ad-compiled-p (symbol-function function))))) | |
3921 | |
3922 (defvar ad-advised-definers | |
3923 '(defun defmacro fset defalias define-function)) | |
3924 | |
3925 (defadvice defun (after ad-definition-hooks first disable preact) | |
3926 "Whenever a function gets re/defined with `defun' all hook functions | |
3927 in `ad-definition-hooks' will be run after the re/definition with | |
3928 `ad-defined-function' bound to the name of the function." | |
3929 (let ((ad-defined-function (ad-get-arg 0))) | |
3930 (run-hooks 'ad-definition-hooks))) | |
3931 | |
3932 (defadvice defmacro (after ad-definition-hooks first disable preact) | |
3933 "Whenever a macro gets re/defined with `defmacro' all hook functions | |
3934 in `ad-definition-hooks' will be run after the re/definition with | |
3935 `ad-defined-function' bound to the name of the function." | |
3936 (let ((ad-defined-function (ad-get-arg 0))) | |
3937 (run-hooks 'ad-definition-hooks))) | |
3938 | |
3939 (defadvice fset (after ad-definition-hooks first disable preact) | |
3940 "Whenever a function gets re/defined with `fset' all hook functions | |
3941 in `ad-definition-hooks' will be run after the re/definition with | |
3942 `ad-defined-function' bound to the name of the function. This advice was | |
3943 mainly created to handle forward-advice for byte-compiled files created | |
3944 by jwz's byte-compiler used in Lemacs. | |
3945 CAUTION: If you need the primitive `fset' behavior either deactivate | |
3946 its advice or use `ad-real-fset' instead!" | |
3947 (let ((ad-defined-function (ad-get-arg 0))) | |
3948 (run-hooks 'ad-definition-hooks))) | |
3949 | |
3950 ;; In Lemacs this is just a noop: | |
3951 (defadvice defalias (after ad-definition-hooks first disable preact) | |
3952 "Whenever a function gets re/defined with `defalias' all hook functions | |
3953 in `ad-definition-hooks' will be run after the re/definition with | |
3954 `ad-defined-function' bound to the name of the function." | |
3955 (let ((ad-defined-function (ad-get-arg 0))) | |
3956 ;; The new `byte-compile' uses `defalias' to set the definition which | |
3957 ;; leads to infinite recursion if it gets to use the advised version | |
3958 ;; (with `fset' this didn't matter because the compiled `byte-compile' | |
3959 ;; called it via its byte-code). Should there be a general provision to | |
3960 ;; avoid recursive application of definition hooks? | |
3961 (ad-with-originals (defalias) | |
3962 (run-hooks 'ad-definition-hooks)))) | |
3963 | |
3964 ;; Needed for Emacs (seems to be an identical copy of `defalias', but | |
3965 ;; it is used in `simple.el' and might be used later, hence, advise it): | |
3966 (defadvice define-function (after ad-definition-hooks first disable preact) | |
3967 "Whenever a function gets re/defined with `define-function' all hook | |
3968 functions in `ad-definition-hooks' will be run after the re/definition with | |
3969 `ad-defined-function' bound to the name of the function." | |
3970 (let ((ad-defined-function (ad-get-arg 0))) | |
3971 (ad-with-originals (define-function) | |
3972 (run-hooks 'ad-definition-hooks)))) | |
3973 | 3890 |
3974 (defadvice documentation (after ad-advised-docstring first disable preact) | 3891 (defadvice documentation (after ad-advised-docstring first disable preact) |
3975 "Builds an advised docstring if FUNCTION is advised." | 3892 "Builds an advised docstring if FUNCTION is advised." |
3976 ;; Because we get the function name from the advised docstring | 3893 ;; Because we get the function name from the advised docstring |
3977 ;; this will work for function names as well as for definitions: | 3894 ;; this will work for function names as well as for definitions: |
3986 ;; Handle optional `raw' argument: | 3903 ;; Handle optional `raw' argument: |
3987 (if (not (ad-get-arg 1)) | 3904 (if (not (ad-get-arg 1)) |
3988 (setq ad-return-value | 3905 (setq ad-return-value |
3989 (substitute-command-keys ad-return-value)))))))) | 3906 (substitute-command-keys ad-return-value)))))))) |
3990 | 3907 |
3991 ;; The following two advised functions are a (hopefully temporary) kludge | |
3992 ;; to fix a problem with the compilation of embedded (or non-top-level) | |
3993 ;; `defun/defmacro's when automatic activation of advice is enabled. For | |
3994 ;; the time of the compilation they backdefine `defun/defmacro' to their | |
3995 ;; original definition to make sure they are not treated as plain macros. | |
3996 ;; Both advices are forward advices, hence, they will only be activated if | |
3997 ;; automatic advice activation is enabled, but since that is the actual | |
3998 ;; situation where we have a problem, we can be sure that the advices will | |
3999 ;; be active when we need them. | |
4000 | |
4001 ;; We only need this in Lemacs, because in Emacs it is | |
4002 ;; now taken care of directly by the byte-compiler: | |
4003 (cond ((ad-lemacs-p) | |
4004 | |
4005 (defvar ad-advised-byte-compilers | |
4006 '(byte-compile-from-buffer byte-compile-top-level)) | |
4007 | |
4008 (defadvice byte-compile-from-buffer (around ad-deactivate-defun-defmacro | |
4009 first disable preact) | |
4010 "Deactivates `defun/defmacro' for proper compilation when they are embedded." | |
4011 (let (;; make sure no `require' starts them again by accident: | |
4012 (ad-advised-definers '(fset defalias define-function))) | |
4013 (ad-with-originals (defun defmacro) | |
4014 ad-do-it))) | |
4015 | |
4016 (defadvice byte-compile-top-level (around ad-deactivate-defun-defmacro | |
4017 first disable preact) | |
4018 "Deactivates `defun/defmacro' for proper compilation when they are embedded." | |
4019 (let (;; make sure no `require' starts them again by accident: | |
4020 (ad-advised-definers '(fset defalias define-function))) | |
4021 (ad-with-originals (defun defmacro) | |
4022 ad-do-it))) | |
4023 | |
4024 )) ;; end of cond | |
4025 | |
4026 ;; Make sure advice-infos are not allocated in pure space | |
4027 ;; (this might not be necessary anymore): | |
4028 (ad-dolist (advised-function (cons 'documentation | |
4029 (append ad-advised-definers | |
4030 (if (ad-lemacs-p) | |
4031 ad-advised-byte-compilers)))) | |
4032 (ad-set-advice-info advised-function (ad-copy-advice-info advised-function))) | |
4033 | |
4034 | |
4035 ;; @@ Forward advice support for jwz's byte-compiler (M-x serious-HACK-mode-on) | |
4036 ;; ============================================================================ | |
4037 ;; Jamie Zawinski's optimizing byte-compiler used in v19 (and by some daring | |
4038 ;; folks in v18) produces compiled files that do not define functions via | |
4039 ;; explicit calls to `defun/defmacro', it rather uses `fset' for functions with | |
4040 ;; documentation strings, and hunks of byte-code for sets of functions without | |
4041 ;; any documentation. In Jamie's byte-compiler a series of compiled functions | |
4042 ;; without docstrings get hunked as | |
4043 ;; (progn (fset 'f1 <code1>) (fset 'f2 <code2>) ...). | |
4044 ;; The resulting progn will be compiled and the compiled form will be written | |
4045 ;; to the compiled file as `(byte-code [progn-code] [constants] [depth])'. To | |
4046 ;; handle forward advice we have to know when functions get defined so we can | |
4047 ;; activate any advice there might be. For standard v18 byte-compiled files | |
4048 ;; we can do this by simply advising `defun/defmacro' because these subrs are | |
4049 ;; evaluated explicitly when such a file is loaded. For Jamie's v19 compiler | |
4050 ;; our only choice is to additionally advise `fset' and change the subr | |
4051 ;; `byte-code' such that it analyzes its byte-code string looking for fset's | |
4052 ;; when we are currently loading a file. In v19 the general overhead caused | |
4053 ;; by the advice of `byte-code' shouldn't be too bad, because byte-compiled | |
4054 ;; functions do not call byte-code explicitly (as done in v18). In v18 this | |
4055 ;; is a problem because with the changed `byte-code' function function calls | |
4056 ;; become more expensive. | |
4057 ;; | |
4058 ;; Wish-List: | |
4059 ;; - special defining functions for use in byte-compiled files, e.g., | |
4060 ;; `byte-compile-fset' and `byte-code-tl' which do the same as their | |
4061 ;; standard brothers, but which can be advised for forward advice without | |
4062 ;; the problems that advising `byte-code' generates. | |
4063 ;; - More generally, a symbol definition hook that could be used for | |
4064 ;; forward advice and related purposes. | |
4065 ;; | |
4066 ;; Until then: For the analysis of the byte-code string we simply scan it for | |
4067 ;; an `fset' opcode (M in ascii) that is preceded by two constant references, | |
4068 ;; the first of which points to the function name and the second to its code. | |
4069 ;; A constant reference can either be a simple one-byte one, or a three-byte | |
4070 ;; one if the function has more than 64 constants. The scanning can pretty | |
4071 ;; efficiently be done with a regular expression. Here it goes: | |
4072 | |
4073 ;; Have to hardcode these opcodes if I don't | |
4074 ;; want to require the byte-compiler: | |
4075 (defvar byte-constant 192) | |
4076 (defvar byte-constant-limit 64) | |
4077 (defvar byte-constant2 129) | |
4078 (defvar byte-fset 77) | |
4079 | |
4080 ;; Matches a byte-compiled fset operation with two constant arguments: | |
4081 (defvar ad-byte-code-fset-regexp | |
4082 (let* ((constant-reference | |
4083 (format "[%s-%s]" | |
4084 (char-to-string byte-constant) | |
4085 (char-to-string (+ byte-constant (1- byte-constant-limit))))) | |
4086 (constant2-reference | |
4087 ;; \0 makes it necessary to use concat instead of format in 18.57: | |
4088 (concat (char-to-string byte-constant2) "[\0-\377][\0-\377]")) | |
4089 (fset-opcode (char-to-string byte-fset))) | |
4090 (concat "\\(" constant-reference "\\|" constant2-reference "\\)" | |
4091 "\\(" constant-reference "\\|" constant2-reference "\\)" | |
4092 fset-opcode))) | |
4093 | |
4094 (defun ad-find-fset-in-byte-code (code constants start) | |
4095 ;;"Finds the first two-constant fset operation in CODE after START. | |
4096 ;;Returns a three element list consisting of the name of the defined | |
4097 ;;function, its code (both taken from the CONSTANTS vector), and an | |
4098 ;;advanced start index." | |
4099 (let ((start | |
4100 ;; The odd case that this regexp matches something that isn't an | |
4101 ;; actual fset operation is handled by additional tests and a | |
4102 ;; condition handler in ad-scan-byte-code-for-fsets: | |
4103 (string-match ad-byte-code-fset-regexp code start)) | |
4104 name-index code-index) | |
4105 (cond (start | |
4106 (cond ((= (aref code start) byte-constant2) | |
4107 (setq name-index | |
4108 (+ (aref code (setq start (1+ start))) | |
4109 (* (aref code (setq start (1+ start))) 256))) | |
4110 (setq start (1+ start))) | |
4111 (t (setq name-index (- (aref code start) byte-constant)) | |
4112 (setq start (1+ start)))) | |
4113 (cond ((= (aref code start) byte-constant2) | |
4114 (setq code-index | |
4115 (+ (aref code (setq start (1+ start))) | |
4116 (* (aref code (setq start (1+ start))) 256))) | |
4117 (setq start (1+ start))) | |
4118 (t (setq code-index (- (aref code start) byte-constant)) | |
4119 (setq start (1+ start)))) | |
4120 (list (aref constants name-index) | |
4121 (aref constants code-index) | |
4122 ;; start points to fset opcode: | |
4123 start)) | |
4124 (t nil)))) | |
4125 | |
4126 (defun ad-scan-byte-code-for-fsets (ad-code ad-constants) | |
4127 ;; In case anything in here goes wrong we reset `byte-code' to its real | |
4128 ;; identity. In particular, the handler of the condition-case uses | |
4129 ;; `byte-code', so it better be the real one if we have an error: | |
4130 (ad-real-fset 'byte-code (symbol-function 'ad-real-byte-code)) | |
4131 (condition-case nil | |
4132 (let ((fset-args '(0 0 0))) | |
4133 (while (setq fset-args (ad-find-fset-in-byte-code | |
4134 ad-code ad-constants | |
4135 (car (cdr (cdr fset-args))))) | |
4136 (if (and (symbolp (car fset-args)) | |
4137 (fboundp (car fset-args)) | |
4138 (eq (symbol-function (car fset-args)) | |
4139 (car (cdr fset-args)))) | |
4140 ;; We've found an fset that was executed during this call | |
4141 ;; to byte-code, and whose definition is still eq to the | |
4142 ;; current definition of the defined function: | |
4143 (let ((ad-defined-function (car fset-args))) | |
4144 (run-hooks 'ad-definition-hooks)))) | |
4145 ;; Everything worked fine, readvise `byte-code': | |
4146 (ad-real-fset 'byte-code (symbol-function 'ad-advised-byte-code))) | |
4147 (error nil))) | |
4148 | |
4149 ;; CAUTION: Don't try this at home!! Changing `byte-code' is a | |
4150 ;; pretty suicidal activity. | |
4151 ;; To allow v19 forward advice we cannot advise `byte-code' as a subr as | |
4152 ;; we did for `defun' etc., because `ad-subr-args' of the advised | |
4153 ;; `byte-code' would shield references to `ad-subr-args' in the body of | |
4154 ;; v18 compiled advised subrs such as `defun', and, more importantly, the | |
4155 ;; changed version of `byte-code' has to be as small and efficient as | |
4156 ;; possible because it is used in every call to a compiled function. | |
4157 ;; Hence, we previously saved its original definition and redefine it as | |
4158 ;; the following function - yuck: | |
4159 | |
4160 ;; The arguments will scope around the body of every byte-compiled | |
4161 ;; function, hence they have to be obscure enough to not be equal to any | |
4162 ;; global or argument variable referenced by any compiled function: | |
4163 (defun ad-advised-byte-code (ad-cOdE ad-cOnStAnTs ad-dEpTh) | |
4164 "Modified version of `byte-code' subr used by the Advice package. | |
4165 `byte-code' has been modified to allow automatic activation of forward | |
4166 advice for functions that are defined in byte-compiled files. | |
4167 See `ad-real-byte-code' for original documentation." | |
4168 (prog1 (ad-real-byte-code ad-cOdE ad-cOnStAnTs ad-dEpTh) | |
4169 (if load-in-progress | |
4170 (ad-scan-byte-code-for-fsets ad-cOdE ad-cOnStAnTs)))) | |
4171 | |
4172 (defun ad-recover-byte-code () | |
4173 "Recovers the real `byte-code' functionality." | |
4174 (interactive) | |
4175 (ad-real-fset 'byte-code (symbol-function 'ad-real-byte-code))) | |
4176 | |
4177 (defun ad-enable-definition-hooks () | |
4178 ;;"Enables definition hooks by redefining definition primitives. | |
4179 ;;Activates the advice of defun/defmacro/fset and redefines `byte-code'. | |
4180 ;;Redefining these primitives might lead to problems. Use | |
4181 ;;`ad-disable-definition-hooks' or `ad-stop-advice' in such a case | |
4182 ;;to establish a safe state." | |
4183 (ad-dolist (definer ad-advised-definers) | |
4184 (ad-enable-advice definer 'after 'ad-definition-hooks) | |
4185 (ad-activate definer 'compile)) | |
4186 (if (ad-lemacs-p) | |
4187 (ad-dolist (byte-compiler ad-advised-byte-compilers) | |
4188 (ad-enable-advice byte-compiler 'around 'ad-deactivate-defun-defmacro) | |
4189 (ad-activate byte-compiler 'compile))) | |
4190 ;; Now redefine byte-code... | |
4191 (ad-real-fset 'byte-code (symbol-function 'ad-advised-byte-code))) | |
4192 | |
4193 (defun ad-disable-definition-hooks () | |
4194 ;;"Disables definition hooks by resetting definition primitives." | |
4195 (ad-recover-byte-code) | |
4196 (ad-dolist (definer ad-advised-definers) | |
4197 (ad-disable-advice definer 'after 'ad-definition-hooks) | |
4198 (ad-update definer)) | |
4199 (if (ad-lemacs-p) | |
4200 (ad-dolist (byte-compiler ad-advised-byte-compilers) | |
4201 (ad-disable-advice byte-compiler 'around 'ad-deactivate-defun-defmacro) | |
4202 (ad-update byte-compiler 'compile)))) | |
4203 | |
4204 | 3908 |
4205 ;; @@ Starting, stopping and recovering from the advice package magic: | 3909 ;; @@ Starting, stopping and recovering from the advice package magic: |
4206 ;; =================================================================== | 3910 ;; =================================================================== |
4207 | 3911 |
4208 ;;;###autoload | |
4209 (defun ad-start-advice () | 3912 (defun ad-start-advice () |
4210 "Redefines some primitives to start the advice magic. | 3913 "Starts the automatic advice handling magic." |
4211 If `ad-activate-on-definition' is t then advice information will | |
4212 automatically get activated whenever an advised function gets defined or | |
4213 redefined. This will enable goodies such as forward advice and | |
4214 automatically enable function definition hooks. If its value is nil but | |
4215 the value of `ad-enable-definition-hooks' is t then definition hooks | |
4216 will be enabled without having automatic advice activation, otherwise | |
4217 function definition hooks will be disabled too. If definition hooks are | |
4218 enabled then functions stored in `ad-definition-hooks' are run whenever | |
4219 a function gets defined or redefined." | |
4220 (interactive) | 3914 (interactive) |
3915 ;; Advising `ad-activate' means death!! | |
3916 (ad-set-advice-info 'ad-activate nil) | |
3917 (ad-safe-fset 'ad-activate 'ad-activate-on) | |
4221 (ad-enable-advice 'documentation 'after 'ad-advised-docstring) | 3918 (ad-enable-advice 'documentation 'after 'ad-advised-docstring) |
4222 (ad-activate 'documentation 'compile) | 3919 (ad-activate-on 'documentation 'compile)) |
4223 (if (or ad-activate-on-definition | |
4224 ad-enable-definition-hooks) | |
4225 (ad-enable-definition-hooks) | |
4226 (ad-disable-definition-hooks)) | |
4227 (setq ad-definition-hooks | |
4228 (if ad-activate-on-definition | |
4229 (if (memq 'ad-activate-defined-function ad-definition-hooks) | |
4230 ad-definition-hooks | |
4231 (cons 'ad-activate-defined-function ad-definition-hooks)) | |
4232 (delq 'ad-activate-defined-function ad-definition-hooks)))) | |
4233 | 3920 |
4234 (defun ad-stop-advice () | 3921 (defun ad-stop-advice () |
4235 "Undefines some primitives to stop the advice magic. | 3922 "Stops the automatic advice handling magic. |
4236 This can also be used to recover from advice related emergencies." | 3923 You should only need this in case of Advice-related emergencies." |
4237 (interactive) | 3924 (interactive) |
4238 (ad-recover-byte-code) | 3925 ;; Advising `ad-activate' means death!! |
3926 (ad-set-advice-info 'ad-activate nil) | |
4239 (ad-disable-advice 'documentation 'after 'ad-advised-docstring) | 3927 (ad-disable-advice 'documentation 'after 'ad-advised-docstring) |
4240 (ad-update 'documentation) | 3928 (ad-update 'documentation) |
4241 (ad-disable-definition-hooks) | 3929 (ad-safe-fset 'ad-activate 'ad-activate-off)) |
4242 (setq ad-definition-hooks | |
4243 (delq 'ad-activate-defined-function ad-definition-hooks))) | |
4244 | 3930 |
4245 (defun ad-recover-normality () | 3931 (defun ad-recover-normality () |
4246 "Undoes all advice related redefinitions and unadvises everything. | 3932 "Undoes all advice related redefinitions and unadvises everything. |
4247 Use only in REAL emergencies." | 3933 Use only in REAL emergencies." |
4248 (interactive) | 3934 (interactive) |
4249 (ad-recover-byte-code) | 3935 ;; Advising `ad-activate' means death!! |
3936 (ad-set-advice-info 'ad-activate nil) | |
3937 (ad-safe-fset 'ad-activate 'ad-activate-off) | |
4250 (ad-recover-all) | 3938 (ad-recover-all) |
4251 (setq ad-advised-functions nil)) | 3939 (setq ad-advised-functions nil)) |
4252 | 3940 |
4253 (if (and ad-start-advice-on-load | 3941 ;; Until the Advice-related changes to `data.c' are part of Lemacs we |
4254 ;; ...but only if we are compiled: | 3942 ;; have to load the old implementation of advice activation hooks: |
4255 (ad-compiled-p (symbol-function 'ad-start-advice))) | 3943 (if (ad-lemacs-p) |
4256 (ad-start-advice)) | 3944 (require 'ad-hooks)) |
3945 | |
3946 (ad-start-advice) | |
4257 | 3947 |
4258 (provide 'advice) | 3948 (provide 'advice) |
4259 | 3949 |
4260 ;;; advice.el ends here | 3950 ;;; advice.el ends here |
4261 |