* lisp/subr.el (pop): Use `car-safe'.
[bpt/emacs.git] / lisp / emacs-lisp / advice.el
index a947dce..7996f9a 100644 (file)
@@ -1,6 +1,6 @@
 ;;; advice.el --- An overloading mechanism for Emacs Lisp functions  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 2000-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2000-2013 Free Software Foundation, Inc.
 
 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
 ;; Maintainer: FSF
 ;; Advice implements forward advice mainly via the following: 1) Separation
 ;; of advice definition and activation that makes it possible to accumulate
 ;; advice information without having the original function already defined,
-;; 2) special versions of the built-in functions `fset/defalias' which check
-;; for advice information whenever they define a function.  If advice
-;; information was found then the advice will immediately get activated when
-;; the function gets defined.
+;; 2) Use of the `defalias-fset-function' symbol property which lets
+;; us advise the function when it gets defined.
 
 ;; Automatic advice activation means, that whenever a function gets defined
-;; with either `defun', `defmacro', `fset' or by loading a byte-compiled
+;; with either `defun', `defmacro', `defalias' or by loading a byte-compiled
 ;; file, and the function has some advice-info stored with it then that
 ;; advice will get activated right away.
 
@@ -2142,14 +2140,6 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
   "Take a macro function DEFINITION and make a lambda out of it."
   `(cdr ,definition))
 
-(defmacro ad-subr-p (definition)
-  ;;"non-nil if DEFINITION is a subr."
-  (list 'subrp definition))
-
-(defmacro ad-macro-p (definition)
-  ;;"non-nil if DEFINITION is a macro."
-  `(eq (car-safe ,definition) 'macro))
-
 (defmacro ad-lambda-p (definition)
   ;;"non-nil if DEFINITION is a lambda expression."
   `(eq (car-safe ,definition) 'lambda))
@@ -2162,12 +2152,12 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
 (defmacro ad-compiled-p (definition)
   "Return non-nil if DEFINITION is a compiled byte-code object."
   `(or (byte-code-function-p ,definition)
-    (and (ad-macro-p ,definition)
-     (byte-code-function-p (ad-lambdafy ,definition)))))
+       (and (macrop ,definition)
+            (byte-code-function-p (ad-lambdafy ,definition)))))
 
 (defmacro ad-compiled-code (compiled-definition)
   "Return the byte-code object of a COMPILED-DEFINITION."
-  `(if (ad-macro-p ,compiled-definition)
+  `(if (macrop ,compiled-definition)
     (ad-lambdafy ,compiled-definition)
     ,compiled-definition))
 
@@ -2175,7 +2165,7 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
   "Return the lambda expression of a function/macro/advice DEFINITION."
   (cond ((ad-lambda-p definition)
         definition)
-       ((ad-macro-p definition)
+       ((macrop definition)
         (ad-lambdafy definition))
        ((ad-advice-p definition)
         (cdr definition))
@@ -2185,7 +2175,7 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
   "Return the argument list of DEFINITION."
   (require 'help-fns)
   (help-function-arglist
-   (if (or (ad-macro-p definition) (ad-advice-p definition))
+   (if (or (macrop definition) (ad-advice-p definition))
        (cdr definition)
      definition)
    'preserve-names))
@@ -2231,7 +2221,7 @@ definition (see the code for `documentation')."
 (defun ad-advised-definition-p (definition)
   "Return non-nil if DEFINITION was generated from advice information."
   (if (or (ad-lambda-p definition)
-         (ad-macro-p definition)
+         (macrop definition)
          (ad-compiled-p definition))
       (let ((docstring (ad-docstring definition)))
        (and (stringp docstring)
@@ -2244,8 +2234,8 @@ definition (see the code for `documentation')."
   ;; representations, so cache entries preactivated with version
   ;; 1 can't be used.
   (cond
-   ((ad-macro-p definition) 'macro2)
-   ((ad-subr-p definition) 'subr2)
+   ((macrop definition) 'macro2)
+   ((subrp definition) 'subr2)
    ((or (ad-lambda-p definition) (ad-compiled-p definition)) 'fun2)
    ((ad-advice-p definition) 'advice2))) ;; FIXME: Can this ever happen?
 
@@ -2275,14 +2265,13 @@ For that it has to be fbound with a non-autoload definition."
   "True if FUNCTION has an interpreted definition that can be compiled."
   (and (ad-has-proper-definition function)
        (or (ad-lambda-p (symbol-function function))
-          (ad-macro-p (symbol-function function)))
+          (macrop (symbol-function function)))
        (not (ad-compiled-p (symbol-function function)))))
 
 (defvar warning-suppress-types)         ;From warnings.el.
 (defun ad-compile-function (function)
   "Byte-compile the assembled advice function."
   (require 'bytecomp)
-  (require 'warnings)  ;To define warning-suppress-types before we let-bind it.
   (let ((byte-compile-warnings byte-compile-warnings)
         ;; Don't pop up windows showing byte-compiler warnings.
         (warning-suppress-types '((bytecomp))))
@@ -2868,10 +2857,8 @@ advised definition from scratch."
 
 (defun ad-preactivate-advice (function advice class position)
   "Preactivate FUNCTION and returns the constructed cache."
-  (let* ((function-defined-p (fboundp function))
-        (old-definition
-         (if function-defined-p
-             (symbol-function function)))
+  (let* ((advicefunname (ad-get-advice-info-field function 'advicefunname))
+         (old-advice (symbol-function advicefunname))
         (old-advice-info (ad-copy-advice-info function))
         (ad-advised-functions ad-advised-functions))
     (unwind-protect
@@ -2885,10 +2872,9 @@ advised definition from scratch."
              (list (ad-get-cache-definition function)
                    (ad-get-cache-id function))))
       (ad-set-advice-info function old-advice-info)
-      ;; Don't `fset' function to nil if it was previously unbound:
-      (if function-defined-p
-         (fset function old-definition)
-       (fmakunbound function)))))
+      (advice-remove function advicefunname)
+      (fset advicefunname old-advice)
+      (if old-advice (advice-add function :around advicefunname)))))
 
 
 ;; @@ Activation and definition handling:
@@ -2908,7 +2894,7 @@ If COMPILE is nil then the result depends on the value of
    ((eq ad-default-compilation-action 'never) nil)
    ((eq ad-default-compilation-action 'always) t)
    ((eq ad-default-compilation-action 'like-original)
-    (or (ad-subr-p (ad-get-orig-definition function))
+    (or (subrp (ad-get-orig-definition function))
         (ad-compiled-p (ad-get-orig-definition function))))
    ;; everything else means `maybe':
    (t (featurep 'byte-compile))))
@@ -2917,13 +2903,18 @@ If COMPILE is nil then the result depends on the value of
   "Redefine FUNCTION with its advised definition from cache or scratch.
 The resulting FUNCTION will be compiled if `ad-should-compile' returns t.
 The current definition and its cache-id will be put into the cache."
-  (let ((verified-cached-definition
-        (if (ad-verify-cache-id function)
-            (ad-get-cache-definition function)))
-        (advicefunname (ad-get-advice-info-field function 'advicefunname)))
+  (let* ((verified-cached-definition
+          (if (ad-verify-cache-id function)
+              (ad-get-cache-definition function)))
+         (advicefunname (ad-get-advice-info-field function 'advicefunname))
+         (old-ispec (interactive-form advicefunname)))
     (fset advicefunname
           (or verified-cached-definition
               (ad-make-advised-definition function)))
+    (unless (equal (interactive-form advicefunname) old-ispec)
+      ;; If the interactive-spec of advicefunname has changed, force nadvice to
+      ;; refresh its copy.
+      (advice-remove function advicefunname))
     (advice-add function :around advicefunname)
     (if (ad-should-compile function compile)
        (ad-compile-function function))
@@ -3199,7 +3190,7 @@ See Info node `(elisp)Advising Functions' for comprehensive documentation.
 usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
           [DOCSTRING] [INTERACTIVE-FORM]
           BODY...)"
-  (declare (doc-string 3)
+  (declare (doc-string 3) (indent 2)
            (debug (&define name  ;; thing being advised.
                            (name ;; class is [&or "before" "around" "after"
                                  ;;               "activation" "deactivation"]
@@ -3250,7 +3241,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
              `((ad-set-cache
                 ',function
                 ;; the function will get compiled:
-                ,(cond ((ad-macro-p (car preactivation))
+                ,(cond ((macrop (car preactivation))
                         `(ad-macrofy
                           (function
                            ,(ad-lambdafy