Merge from emacs--rel--22
[bpt/emacs.git] / lisp / emacs-lisp / bytecomp.el
index 220a7d8..cdc93cf 100644 (file)
@@ -1,7 +1,7 @@
 ;;; bytecomp.el --- compilation of Lisp code into byte code
 
-;; Copyright (C) 1985,86,87,92,94,1998,2000,01,02,03,2004
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1987, 1992, 1994, 1998, 2000, 2001, 2002,
+;;   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
 ;;     Hallvard Furuseth <hbf@ulrik.uio.no>
@@ -22,8 +22,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;;                             `obsolete'  (obsolete variables and functions)
 ;;                             `noruntime' (calls to functions only defined
 ;;                                          within `eval-when-compile')
+;;                             `cl-functions' (calls to CL functions)
+;;                             `interactive-only' (calls to commands that are
+;;                                                not good to call from Lisp)
+;;                             `make-local' (dubious calls to
+;;                                           `make-variable-buffer-local')
 ;; byte-compile-compatibility  Whether the compiler should
 ;;                             generate .elc files which can be loaded into
 ;;                             generic emacs 18.
 
 
 (defgroup bytecomp nil
-  "Emacs Lisp byte-compiler"
+  "Emacs Lisp byte-compiler."
   :group 'lisp)
 
 (defcustom emacs-lisp-file-regexp (if (eq system-type 'vax-vms)
@@ -216,7 +221,9 @@ if you change this variable."
     ;; The user may want to redefine this along with emacs-lisp-file-regexp,
     ;; so only define it if it is undefined.
     (defun byte-compile-dest-file (filename)
-      "Convert an Emacs Lisp source file name to a compiled file name."
+      "Convert an Emacs Lisp source file name to a compiled file name.
+If FILENAME matches `emacs-lisp-file-regexp' (by default, files
+with the extension `.el'), add `c' to it; otherwise add `.elc'."
       (setq filename (byte-compiler-base-file-name filename))
       (setq filename (file-name-sans-versions filename))
       (cond ((eq system-type 'vax-vms)
@@ -261,11 +268,12 @@ facilities that have been added more recently."
 ;; this way can never be run in Emacs 18, and may even cause it to crash.")
 
 (defcustom byte-optimize t
-  "*Enables optimization in the byte compiler.
-nil means don't do any optimization.
-t means do all optimizations.
-`source' means do source-level optimizations only.
-`byte' means do code-level optimizations only."
+  "*Enable optimization in the byte compiler.
+Possible values are:
+  nil      - no optimization
+  t        - all optimizations
+  `source' - source-level optimizations only
+  `byte'   - code-level optimizations only"
   :group 'bytecomp
   :type '(choice (const :tag "none" nil)
                 (const :tag "all" t)
@@ -290,6 +298,11 @@ For example, add  -*-byte-compile-dynamic: t;-*- on the first line.
 
 When this option is true, if you load the compiled file and then move it,
 the functions you loaded will not be able to run.")
+;;;###autoload(put 'byte-compile-dynamic 'safe-local-variable 'booleanp)
+
+(defvar byte-compile-disable-print-circle nil
+  "If non-nil, disable `print-circle' on printing a byte-compiled code.")
+;;;###autoload(put 'byte-compile-disable-print-circle 'safe-local-variable 'booleanp)
 
 (defcustom byte-compile-dynamic-docstrings t
   "*If non-nil, compile doc strings for lazy access.
@@ -308,6 +321,7 @@ You can also set the variable globally.
 This option is enabled by default because it reduces Emacs memory usage."
   :group 'bytecomp
   :type 'boolean)
+;;;###autoload(put 'byte-compile-dynamic-docstrings 'safe-local-variable 'booleanp)
 
 (defcustom byte-optimize-log nil
   "*If true, the byte-compiler will log its optimizations into *Compile-Log*.
@@ -325,36 +339,61 @@ If it is 'byte, then only byte-level optimizations will be logged."
   :type 'boolean)
 
 (defconst byte-compile-warning-types
-  '(redefine callargs free-vars unresolved obsolete noruntime cl-functions)
+  '(redefine callargs free-vars unresolved
+            obsolete noruntime cl-functions interactive-only)
   "The list of warning types used when `byte-compile-warnings' is t.")
 (defcustom byte-compile-warnings t
   "*List of warnings that the byte-compiler should issue (t for all).
 
-Elements of the list may be be:
+Elements of the list may be:
 
   free-vars   references to variables not in the current lexical scope.
   unresolved  calls to unknown functions.
-  callargs    lambda calls with args that don't match the definition.
-  redefine    function cell redefined from a macro to a lambda or vice
+  callargs    function calls with args that don't match the definition.
+  redefine    function name redefined from a macro to ordinary function or vice
               versa, or redefined to take a different number of arguments.
   obsolete    obsolete variables and functions.
   noruntime   functions that may not be defined at runtime (typically
               defined only under `eval-when-compile').
   cl-functions    calls to runtime functions from the CL package (as
-                 distinguished from macros and aliases)."
+                 distinguished from macros and aliases).
+  interactive-only
+             commands that normally shouldn't be called from Lisp code.
+  make-local  calls to make-variable-buffer-local that may be incorrect."
   :group 'bytecomp
   :type `(choice (const :tag "All" t)
                 (set :menu-tag "Some"
                      (const free-vars) (const unresolved)
                      (const callargs) (const redefine)
-                     (const obsolete) (const noruntime) (const cl-functions))))
+                     (const obsolete) (const noruntime)
+                     (const cl-functions) (const interactive-only)
+                     (const make-local))))
+(put 'byte-compile-warnings 'safe-local-variable 'byte-compile-warnings-safe-p)
+;;;###autoload
+(defun byte-compile-warnings-safe-p (x)
+  (or (booleanp x)
+      (and (listp x)
+          (equal (mapcar
+                  (lambda (e)
+                    (when (memq e '(free-vars unresolved
+                                    callargs redefine
+                                    obsolete noruntime
+                                    cl-functions interactive-only make-local))
+                      e))
+                  x)
+                 x))))
+
+(defvar byte-compile-interactive-only-functions
+  '(beginning-of-buffer end-of-buffer replace-string replace-regexp
+    insert-file insert-buffer insert-file-literally)
+  "List of commands that are not meant to be called from Lisp.")
 
 (defvar byte-compile-not-obsolete-var nil
   "If non-nil, this is a variable that shouldn't be reported as obsolete.")
 
 (defcustom byte-compile-generate-call-tree nil
   "*Non-nil means collect call-graph information when compiling.
-This records functions were called and from where.
+This records which functions were called and from where.
 If the value is t, compilation displays the call graph when it finishes.
 If the value is neither t nor nil, compilation asks you whether to display
 the graph.
@@ -435,11 +474,14 @@ Each element looks like (MACRONAME . DEFINITION).  It is
   "Alist of functions defined in the file being compiled.
 This is so we can inline them when necessary.
 Each element looks like (FUNCTIONNAME . DEFINITION).  It is
-\(FUNCTIONNAME . nil) when a function is redefined as a macro.")
+\(FUNCTIONNAME . nil) when a function is redefined as a macro.
+It is \(FUNCTIONNAME . t) when all we know is that it was defined,
+and we don't know the definition.")
 
 (defvar byte-compile-unresolved-functions nil
   "Alist of undefined functions to which calls have been compiled.
-Used for warnings when the function is not known to be defined or is later
+This variable is only significant whilst compiling an entire buffer.
+Used for warnings when a function is not known to be defined or is later
 defined with incorrect args.")
 
 (defvar byte-compile-noruntime-functions nil
@@ -792,7 +834,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
            (let ((xs (pop hist-new))
                  old-autoloads)
              ;; Make sure the file was not already loaded before.
-             (unless (assoc (car xs) hist-orig)
+             (unless (or (assoc (car xs) hist-orig)
+                         (equal (car xs) "cl"))
                (dolist (s xs)
                  (cond
                   ((symbolp s)
@@ -809,7 +852,16 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
                (when (and (symbolp s) (not (memq s old-autoloads)))
                  (push s byte-compile-noruntime-functions))
                (when (and (consp s) (eq t (car s)))
-                 (push (cdr s) old-autoloads))))))))))
+                 (push (cdr s) old-autoloads)))))))
+      (when (memq 'cl-functions byte-compile-warnings)
+       (let ((hist-new load-history))
+         ;; Go through load-history, look for newly loaded files
+         ;; and mark all the functions defined therein.
+         (while (and hist-new (not (eq hist-new hist-orig)))
+           (let ((xs (pop hist-new)))
+             ;; Make sure the file was not already loaded before.
+             (when (and (equal (car xs) "cl") (not (assoc (car xs) hist-orig)))
+               (byte-compile-find-cl-functions)))))))))
 
 (defun byte-compile-eval-before-compile (form)
   "Evaluate FORM for `eval-and-compile'."
@@ -832,30 +884,29 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 
 ;; Log something that isn't a warning.
 (defmacro byte-compile-log (format-string &rest args)
-  (list 'and
-       'byte-optimize
-       '(memq byte-optimize-log '(t source))
-       (list 'let '((print-escape-newlines t)
-                    (print-level 4)
-                    (print-length 4))
-             (list 'byte-compile-log-1
-                   (cons 'format
-                     (cons format-string
-                       (mapcar
-                        (lambda (x)
-                          (if (symbolp x) (list 'prin1-to-string x) x))
-                        args)))))))
+  `(and
+    byte-optimize
+    (memq byte-optimize-log '(t source))
+    (let ((print-escape-newlines t)
+         (print-level 4)
+         (print-length 4))
+      (byte-compile-log-1
+       (format
+       ,format-string
+       ,@(mapcar
+          (lambda (x) (if (symbolp x) (list 'prin1-to-string x) x))
+          args))))))
 
 ;; Log something that isn't a warning.
 (defun byte-compile-log-1 (string)
-  (save-excursion
-    (byte-goto-log-buffer)
-    (goto-char (point-max))
-    (byte-compile-warning-prefix nil nil)
-    (cond (noninteractive
-          (message " %s" string))
-         (t
-          (insert (format "%s\n" string))))))
+  (with-current-buffer "*Compile-Log*"
+    (let ((inhibit-read-only t))
+      (goto-char (point-max))
+      (byte-compile-warning-prefix nil nil)
+      (cond (noninteractive
+            (message " %s" string))
+           (t
+            (insert (format "%s\n" string)))))))
 
 (defvar byte-compile-read-position nil
   "Character position we began the last `read' from.")
@@ -883,35 +934,38 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 ;; list.  If our current position is after the symbol's position, we
 ;; assume we've already passed that point, and look for the next
 ;; occurrence of the symbol.
+;;
+;; This function should not be called twice for the same occurrence of
+;; a symbol, and it should not be called for symbols generated by the
+;; byte compiler itself; because rather than just fail looking up the
+;; symbol, we may find an occurrence of the symbol further ahead, and
+;; then `byte-compile-last-position' as advanced too far.
+;;
 ;; So your're probably asking yourself: Isn't this function a
 ;; gross hack?  And the answer, of course, would be yes.
 (defun byte-compile-set-symbol-position (sym &optional allow-previous)
   (when byte-compile-read-position
     (let (last entry)
       (while (progn
-           (setq last byte-compile-last-position
-             entry (assq sym read-symbol-positions-list))
-           (when entry
-           (setq byte-compile-last-position
-             (+ byte-compile-read-position (cdr entry))
-             read-symbol-positions-list
-             (byte-compile-delete-first
-              entry read-symbol-positions-list)))
+              (setq last byte-compile-last-position
+                    entry (assq sym read-symbol-positions-list))
+              (when entry
+                (setq byte-compile-last-position
+                      (+ byte-compile-read-position (cdr entry))
+                      read-symbol-positions-list
+                      (byte-compile-delete-first
+                       entry read-symbol-positions-list)))
               (or (and allow-previous (not (= last byte-compile-last-position)))
                   (> last byte-compile-last-position)))))))
 
 (defvar byte-compile-last-warned-form nil)
 (defvar byte-compile-last-logged-file nil)
 
-(defun byte-goto-log-buffer ()
-  (set-buffer (get-buffer-create "*Compile-Log*"))
-  (unless (eq major-mode 'compilation-mode)
-    (compilation-mode)))
-
 ;; This is used as warning-prefix for the compiler.
 ;; It is always called with the warnings buffer current.
 (defun byte-compile-warning-prefix (level entry)
-  (let* ((dir default-directory)
+  (let* ((inhibit-read-only t)
+        (dir default-directory)
         (file (cond ((stringp byte-compile-current-file)
                      (format "%s:" (file-relative-name byte-compile-current-file dir)))
                     ((bufferp byte-compile-current-file)
@@ -921,8 +975,10 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
         (pos (if (and byte-compile-current-file
                       (integerp byte-compile-read-position))
                  (with-current-buffer byte-compile-current-buffer
-                   (format "%d:%d:" (count-lines (point-min)
-                                                 byte-compile-last-position)
+                   (format "%d:%d:" 
+                           (save-excursion
+                             (goto-char byte-compile-last-position)
+                             (1+ (count-lines (point-min) (point-at-bol))))
                            (save-excursion
                              (goto-char byte-compile-last-position)
                              (1+ (current-column)))))
@@ -957,7 +1013,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
        (save-excursion
         (set-buffer (get-buffer-create "*Compile-Log*"))
         (goto-char (point-max))
-        (let* ((dir (and byte-compile-current-file
+        (let* ((inhibit-read-only t)
+               (dir (and byte-compile-current-file
                          (file-name-directory byte-compile-current-file)))
                (was-same (equal default-directory dir))
                pt)
@@ -983,6 +1040,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
           ;; Do this after setting default-directory.
           (unless (eq major-mode 'compilation-mode)
             (compilation-mode))
+          (compilation-forget-errors)
           pt))))
 
 ;; Log a message STRING in *Compile-Log*.
@@ -990,7 +1048,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 (defun byte-compile-log-warning (string &optional fill level)
   (let ((warning-prefix-function 'byte-compile-warning-prefix)
        (warning-type-format "")
-       (warning-fill-prefix (if fill "    ")))
+       (warning-fill-prefix (if fill "    "))
+       (inhibit-read-only t))
     (display-warning 'bytecomp string level "*Compile-Log*")))
 
 (defun byte-compile-warn (format &rest args)
@@ -1014,11 +1073,11 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
         (when (nth 2 new)))
     (byte-compile-set-symbol-position (car form))
     (if (memq 'obsolete byte-compile-warnings)
-       (byte-compile-warn "%s is an obsolete function%s; %s" (car form)
-                          (if when (concat " since " when) "")
+       (byte-compile-warn "`%s' is an obsolete function%s; %s" (car form)
+                          (if when (concat " (as of Emacs " when ")") "")
                           (if (stringp (car new))
                               (car new)
-                            (format "use %s instead." (car new)))))
+                            (format "use `%s' instead." (car new)))))
     (funcall (or handler 'byte-compile-normal-call) form)))
 \f
 ;; Compiler options
@@ -1081,6 +1140,10 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 \f
 ;;; sanity-checking arglists
 
+;; If a function has an entry saying (FUNCTION . t).
+;; that means we know it is defined but we don't know how.
+;; If a function has an entry saying (FUNCTION . nil),
+;; that means treat it as not defined.
 (defun byte-compile-fdefinition (name macro-p)
   (let* ((list (if macro-p
                   byte-compile-macro-environment
@@ -1146,7 +1209,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 (defun byte-compile-callargs-warn (form)
   (let* ((def (or (byte-compile-fdefinition (car form) nil)
                  (byte-compile-fdefinition (car form) t)))
-        (sig (if def
+        (sig (if (and def (not (eq def t)))
                  (byte-compile-arglist-signature
                   (if (eq 'lambda (car-safe def))
                       (nth 1 def)
@@ -1176,7 +1239,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
     (byte-compile-format-warn form)
     ;; Check to see if the function will be available at runtime
     ;; and/or remember its arity if it's unknown.
-    (or (and (or sig (fboundp (car form))) ; might be a subr or autoload.
+    (or (and (or def (fboundp (car form))) ; might be a subr or autoload.
             (not (memq (car form) byte-compile-noruntime-functions)))
        (eq (car form) byte-compile-current-form) ; ## this doesn't work
                                        ; with recursion.
@@ -1187,9 +1250,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
          (if cons
              (or (memq n (cdr cons))
                  (setcdr cons (cons n (cdr cons))))
-           (setq byte-compile-unresolved-functions
-                 (cons (list (car form) n)
-                       byte-compile-unresolved-functions)))))))
+           (push (list (car form) n)
+                 byte-compile-unresolved-functions))))))
 
 (defun byte-compile-format-warn (form)
   "Warn if FORM is `format'-like with inconsistent args.
@@ -1202,7 +1264,7 @@ extra args."
             (get (car form) 'byte-compile-format-like))
     (let ((nfields (with-temp-buffer
                     (insert (nth 1 form))
-                    (goto-char 1)
+                    (goto-char (point-min))
                     (let ((n 0))
                       (while (re-search-forward "%." nil t)
                         (unless (eq ?% (char-after (1+ (match-beginning 0))))
@@ -1217,11 +1279,28 @@ extra args."
 (dolist (elt '(format message error))
   (put elt 'byte-compile-format-like t))
 
+;; Warn if a custom definition fails to specify :group.
+(defun byte-compile-nogroup-warn (form)
+  (let ((keyword-args (cdr (cdr (cdr (cdr form)))))
+        (name (cadr form)))
+    (or (not (eq (car-safe name) 'quote))
+        (and (eq (car form) 'custom-declare-group)
+             (equal name ''emacs))
+        (plist-get keyword-args :group)
+        (not (and (consp name) (eq (car name) 'quote)))
+        (byte-compile-warn
+         "%s for `%s' fails to specify containing group"
+         (cdr (assq (car form)
+                    '((custom-declare-group . defgroup)
+                      (custom-declare-face . defface)
+                      (custom-declare-variable . defcustom))))
+         (cadr name)))))
+
 ;; Warn if the function or macro is being redefined with a different
 ;; number of arguments.
 (defun byte-compile-arglist-warn (form macrop)
   (let ((old (byte-compile-fdefinition (nth 1 form) macrop)))
-    (if old
+    (if (and old (not (eq old t)))
        (let ((sig1 (byte-compile-arglist-signature
                      (if (eq 'lambda (car-safe old))
                          (nth 1 old)
@@ -1268,7 +1347,8 @@ extra args."
   (unless byte-compile-cl-functions
     (dolist (elt load-history)
       (when (and (stringp (car elt))
-                (string-match "^cl\\>" (car elt)))
+                (string-match
+                 "^cl\\>" (file-name-nondirectory (car elt))))
        (setq byte-compile-cl-functions
              (append byte-compile-cl-functions
                      (cdr elt)))))
@@ -1538,11 +1618,13 @@ recompile every `.el' file that already has a `.elc' file."
 This is normally set in local file variables at the end of the elisp file:
 
 ;; Local Variables:\n;; no-byte-compile: t\n;; End: ")
+;;;###autoload(put 'no-byte-compile 'safe-local-variable 'booleanp)
 
 ;;;###autoload
 (defun byte-compile-file (filename &optional load)
   "Compile a file of Lisp code named FILENAME into a file of byte code.
-The output file's name is made by appending `c' to the end of FILENAME.
+The output file's name is generated by passing FILENAME to the
+`byte-compile-dest-file' function (which see).
 With prefix arg (noninteractively: 2nd arg), LOAD the file after compiling.
 The value is non-nil if there were no errors, nil if errors."
 ;;  (interactive "fByte compile file: \nP")
@@ -1599,8 +1681,12 @@ The value is non-nil if there were no errors, nil if errors."
       ;; If they change the file name, then change it for the output also.
       (let ((buffer-file-name filename)
            (default-major-mode 'emacs-lisp-mode)
+           ;; Ignore unsafe local variables.
+           ;; We only care about a few of them for our purposes.
+           (enable-local-variables :safe)
            (enable-local-eval nil))
-        (normal-mode)
+       ;; Arg of t means don't alter enable-local-variables.
+        (normal-mode t)
         (setq filename buffer-file-name))
       ;; Set the default directory, in case an eval-when-compile uses it.
       (setq default-directory (file-name-directory filename)))
@@ -1738,7 +1824,7 @@ With argument, insert value in current buffer after the form."
        (byte-compile-maxdepth 0)
        (byte-compile-output nil)
        ;; This allows us to get the positions of symbols read; it's
-       ;; new in Emacs 21.4.
+       ;; new in Emacs 22.1.
        (read-with-symbol-positions inbuffer)
        (read-symbol-positions-list nil)
        ;;        #### This is bound in b-c-close-variables.
@@ -1747,9 +1833,8 @@ With argument, insert value in current buffer after the form."
        ;;                                 byte-compile-warnings))
        )
     (byte-compile-close-variables
-     (save-excursion
-       (setq outbuffer
-            (set-buffer (get-buffer-create " *Compiler Output*")))
+     (with-current-buffer
+         (setq outbuffer (get-buffer-create " *Compiler Output*"))
        (set-buffer-multibyte t)
        (erase-buffer)
        ;;       (emacs-lisp-mode)
@@ -1763,9 +1848,13 @@ With argument, insert value in current buffer after the form."
        (setq overwrite-mode 'overwrite-mode-binary))
      (displaying-byte-compile-warnings
       (and filename (byte-compile-insert-header filename inbuffer outbuffer))
-      (save-excursion
-       (set-buffer inbuffer)
-       (goto-char 1)
+      (with-current-buffer inbuffer
+       (goto-char (point-min))
+       ;; Should we always do this?  When calling multiple files, it
+       ;; would be useful to delay this warning until all have been
+       ;; compiled.  A: Yes!  b-c-u-f might contain dross from a
+       ;; previous byte-compile.
+       (setq byte-compile-unresolved-functions nil)
 
        ;; Compile the forms from the input buffer.
        (while (progn
@@ -1782,11 +1871,7 @@ With argument, insert value in current buffer after the form."
        ;; Make warnings about unresolved functions
        ;; give the end of the file as their position.
        (setq byte-compile-last-position (point-max))
-       (byte-compile-warn-about-unresolved-functions)
-       ;; Should we always do this?  When calling multiple files, it
-       ;; would be useful to delay this warning until all have
-       ;; been compiled.
-       (setq byte-compile-unresolved-functions nil))
+       (byte-compile-warn-about-unresolved-functions))
       ;; Fix up the header at the front of the output
       ;; if the buffer contains multibyte characters.
       (and filename (byte-compile-fix-header filename inbuffer outbuffer))))
@@ -1833,7 +1918,7 @@ With argument, insert value in current buffer after the form."
   (let ((dynamic-docstrings byte-compile-dynamic-docstrings)
        (dynamic byte-compile-dynamic))
     (set-buffer outbuffer)
-    (goto-char 1)
+    (goto-char (point-min))
     ;; The magic number of .elc files is ";ELC", or 0x3B454C43.  After
     ;; that is the file-format version number (18, 19 or 20) as a
     ;; byte, followed by some nulls.  The primary motivation for doing
@@ -1929,7 +2014,9 @@ With argument, insert value in current buffer after the form."
          (print-length nil)
          (print-level nil)
          (print-quoted t)
-         (print-gensym t))
+         (print-gensym t)
+         (print-circle              ; handle circular data structures
+          (not byte-compile-disable-print-circle)))
       (princ "\n" outbuffer)
       (prin1 form outbuffer)
       nil)))
@@ -1986,6 +2073,8 @@ list that represents a doc string reference.
               ;; print-gensym-alist not to be cleared
               ;; between calls to print functions.
               (print-gensym '(t))
+              (print-circle           ; handle circular data structures
+               (not byte-compile-disable-print-circle))
               print-gensym-alist    ; was used before print-circle existed.
               (print-continuous-numbering t)
               print-number-table
@@ -2082,7 +2171,7 @@ list that represents a doc string reference.
 (defun byte-compile-file-form-defsubst (form)
   (when (assq (nth 1 form) byte-compile-unresolved-functions)
     (setq byte-compile-current-form (nth 1 form))
-    (byte-compile-warn "defsubst %s was used before it was defined"
+    (byte-compile-warn "defsubst `%s' was used before it was defined"
                       (nth 1 form)))
   (byte-compile-file-form
    (macroexpand form byte-compile-macro-environment))
@@ -2101,9 +2190,9 @@ list that represents a doc string reference.
           (eq (car (nth 1 form)) 'quote)
           (consp (cdr (nth 1 form)))
           (symbolp (nth 1 (nth 1 form))))
-      (add-to-list 'byte-compile-function-environment
-                  (cons (nth 1 (nth 1 form))
-                        (cons 'autoload (cdr (cdr form))))))
+      (push (cons (nth 1 (nth 1 form))
+                 (cons 'autoload (cdr (cdr form))))
+           byte-compile-function-environment))
   (if (stringp (nth 3 form))
       form
     ;; No doc string, so we can compile this as a normal form.
@@ -2129,6 +2218,8 @@ list that represents a doc string reference.
 (put 'custom-declare-variable 'byte-hunk-handler
      'byte-compile-file-form-custom-declare-variable)
 (defun byte-compile-file-form-custom-declare-variable (form)
+  (when (memq 'callargs byte-compile-warnings)
+    (byte-compile-nogroup-warn form))
   (when (memq 'free-vars byte-compile-warnings)
     (push (nth 1 (nth 1 form)) byte-compile-bound-variables))
   (let ((tail (nthcdr 4 form)))
@@ -2146,17 +2237,14 @@ list that represents a doc string reference.
       (setq tail (cdr tail))))
   form)
 
-(put 'require 'byte-hunk-handler 'byte-compile-file-form-eval-boundary)
-(defun byte-compile-file-form-eval-boundary (form)
-  (let ((old-load-list current-load-list))
-    (eval form)
-    ;; (require 'cl) turns off warnings for cl functions.
-    (let ((tem current-load-list))
-      (while (not (eq tem old-load-list))
-       (when (equal (car tem) '(require . cl))
-         (setq byte-compile-warnings
-               (remq 'cl-functions byte-compile-warnings)))
-       (setq tem (cdr tem)))))
+(put 'require 'byte-hunk-handler 'byte-compile-file-form-require)
+(defun byte-compile-file-form-require (form)
+  (let ((args (mapcar 'eval (cdr form))))
+    (apply 'require args)
+    ;; Detect (require 'cl) in a way that works even if cl is already loaded.
+    (if (member (car args) '("cl" cl))
+       (setq byte-compile-warnings
+             (remq 'cl-functions byte-compile-warnings))))
   (byte-compile-keep-pending form 'byte-compile-normal-call))
 
 (put 'progn 'byte-hunk-handler 'byte-compile-file-form-progn)
@@ -2212,7 +2300,7 @@ list that represents a doc string reference.
                    (not (assq (nth 1 form)
                               byte-compile-initial-macro-environment)))
               (byte-compile-warn
-                "%s defined multiple times, as both function and macro"
+                "`%s' defined multiple times, as both function and macro"
                 (nth 1 form)))
           (setcdr that-one nil))
          (this-one
@@ -2221,14 +2309,14 @@ list that represents a doc string reference.
                    ;; byte-compiler macros in byte-run.el...
                    (not (assq (nth 1 form)
                               byte-compile-initial-macro-environment)))
-            (byte-compile-warn "%s %s defined multiple times in this file"
+            (byte-compile-warn "%s `%s' defined multiple times in this file"
                                (if macrop "macro" "function")
                                (nth 1 form))))
          ((and (fboundp name)
                (eq (car-safe (symbol-function name))
                    (if macrop 'lambda 'macro)))
           (when (memq 'redefine byte-compile-warnings)
-            (byte-compile-warn "%s %s being redefined as a %s"
+            (byte-compile-warn "%s `%s' being redefined as a %s"
                                (if macrop "function" "macro")
                                (nth 1 form)
                                (if macrop "macro" "function")))
@@ -2255,12 +2343,12 @@ list that represents a doc string reference.
                    (eq (car (car (cdr tail))) 'declare))
          (let ((declaration (car (cdr tail))))
            (setcdr tail (cdr (cdr tail)))
-           (princ `(if macro-declaration-function
+           (prin1 `(if macro-declaration-function
                        (funcall macro-declaration-function
                                 ',name ',declaration))
                   outbuffer)))))
 
-    (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form))))
+    (let* ((new-one (byte-compile-lambda (nthcdr 2 form) t))
           (code (byte-compile-byte-code-maker new-one)))
       (if this-one
          (setcdr this-one new-one)
@@ -2456,10 +2544,16 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 ;; Byte-compile a lambda-expression and return a valid function.
 ;; The value is usually a compiled function but may be the original
 ;; lambda-expression.
-(defun byte-compile-lambda (fun)
-  (unless (eq 'lambda (car-safe fun))
-    (error "Not a lambda list: %S" fun))
-  (byte-compile-set-symbol-position 'lambda)
+;; When ADD-LAMBDA is non-nil, the symbol `lambda' is added as head
+;; of the list FUN and `byte-compile-set-symbol-position' is not called.
+;; Use this feature to avoid calling `byte-compile-set-symbol-position'
+;; for symbols generated by the byte compiler itself.
+(defun byte-compile-lambda (fun &optional add-lambda)
+  (if add-lambda
+      (setq fun (cons 'lambda fun))
+    (unless (eq 'lambda (car-safe fun))
+      (error "Not a lambda list: %S" fun))
+    (byte-compile-set-symbol-position 'lambda))
   (byte-compile-check-lambda-list (nth 1 fun))
   (let* ((arglist (nth 1 fun))
         (byte-compile-bound-variables
@@ -2689,26 +2783,39 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 (defun byte-compile-form (form &optional for-effect)
   (setq form (macroexpand form byte-compile-macro-environment))
   (cond ((not (consp form))
-        (when (symbolp form)
-          (byte-compile-set-symbol-position form))
         (cond ((or (not (symbolp form)) (byte-compile-const-symbol-p form))
+               (when (symbolp form)
+                 (byte-compile-set-symbol-position form))
                (byte-compile-constant form))
               ((and for-effect byte-compile-delete-errors)
+               (when (symbolp form)
+                 (byte-compile-set-symbol-position form))
                (setq for-effect nil))
               (t (byte-compile-variable-ref 'byte-varref form))))
        ((symbolp (car form))
         (let* ((fn (car form))
                (handler (get fn 'byte-compile)))
-          (byte-compile-set-symbol-position fn)
           (when (byte-compile-const-symbol-p fn)
-            (byte-compile-warn "%s called as a function" fn))
+            (byte-compile-warn "`%s' called as a function" fn))
+          (and (memq 'interactive-only byte-compile-warnings)
+               (memq fn byte-compile-interactive-only-functions)
+               (byte-compile-warn "`%s' used from Lisp code\n\
+That command is designed for interactive use only" fn))
           (if (and handler
-                   (or (not (byte-compile-version-cond
-                             byte-compile-compatibility))
-                       (not (get (get fn 'byte-opcode) 'emacs19-opcode))))
-              (funcall handler form)
-            (if (memq 'callargs byte-compile-warnings)
-                (byte-compile-callargs-warn form))
+                    ;; Make sure that function exists.  This is important
+                    ;; for CL compiler macros since the symbol may be
+                    ;; `cl-byte-compile-compiler-macro' but if CL isn't
+                    ;; loaded, this function doesn't exist.
+                    (or (not (memq handler '(cl-byte-compile-compiler-macro)))
+                        (functionp handler))
+                   (not (and (byte-compile-version-cond
+                               byte-compile-compatibility)
+                              (get (get fn 'byte-opcode) 'emacs19-opcode))))
+               (funcall handler form)
+            (when (memq 'callargs byte-compile-warnings)
+              (if (memq fn '(custom-declare-group custom-declare-variable custom-declare-face))
+                  (byte-compile-nogroup-warn form))
+              (byte-compile-callargs-warn form))
             (byte-compile-normal-call form))
           (if (memq 'cl-functions byte-compile-warnings)
               (byte-compile-cl-warn form))))
@@ -2736,9 +2843,9 @@ If FORM is a lambda or a macro, byte-compile it as a function."
   (if (or (not (symbolp var))
          (byte-compile-const-symbol-p var (not (eq base-op 'byte-varref))))
       (byte-compile-warn
-       (cond ((eq base-op 'byte-varbind) "attempt to let-bind %s %s")
-            ((eq base-op 'byte-varset) "variable assignment to %s %s")
-            (t "variable reference to %s %s"))
+       (cond ((eq base-op 'byte-varbind) "attempt to let-bind %s `%s'")
+            ((eq base-op 'byte-varset) "variable assignment to %s `%s'")
+            (t "variable reference to %s `%s'"))
        (if (symbolp var) "constant" "nonvariable")
        (prin1-to-string var))
     (if (and (get var 'byte-obsolete-variable)
@@ -2746,11 +2853,11 @@ If FORM is a lambda or a macro, byte-compile it as a function."
             (not (eq var byte-compile-not-obsolete-var)))
        (let* ((ob (get var 'byte-obsolete-variable))
               (when (cdr ob)))
-         (byte-compile-warn "%s is an obsolete variable%s; %s" var
-                            (if when (concat " since " when) "")
+         (byte-compile-warn "`%s' is an obsolete variable%s; %s" var
+                            (if when (concat " (as of Emacs " when ")") "")
                             (if (stringp (car ob))
                                 (car ob)
-                              (format "use %s instead." (car ob))))))
+                              (format "use `%s' instead." (car ob))))))
     (if (memq 'free-vars byte-compile-warnings)
        (if (eq base-op 'byte-varbind)
            (push var byte-compile-bound-variables)
@@ -2759,11 +2866,11 @@ If FORM is a lambda or a macro, byte-compile it as a function."
              (if (eq base-op 'byte-varset)
                  (or (memq var byte-compile-free-assignments)
                      (progn
-                       (byte-compile-warn "assignment to free variable %s" var)
+                       (byte-compile-warn "assignment to free variable `%s'" var)
                        (push var byte-compile-free-assignments)))
                (or (memq var byte-compile-free-references)
                    (progn
-                     (byte-compile-warn "reference to free variable %s" var)
+                     (byte-compile-warn "reference to free variable `%s'" var)
                      (push var byte-compile-free-references))))))))
   (let ((tmp (assq var byte-compile-variables)))
     (unless tmp
@@ -2773,8 +2880,12 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 
 (defmacro byte-compile-get-constant (const)
   `(or (if (stringp ,const)
-          (assoc-default ,const byte-compile-constants
-                         'equal-including-properties nil)
+          ;; In a string constant, treat properties as significant.
+          (let (result)
+            (dolist (elt byte-compile-constants)
+              (if (equal-including-properties (car elt) ,const)
+                  (setq result elt)))
+            result)
         (assq ,const byte-compile-constants))
        (car (setq byte-compile-constants
                  (cons (list ,const) byte-compile-constants)))))
@@ -2868,9 +2979,6 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 (put 'byte-concatN 'byte-opcode-invert 'concat)
 (put 'byte-insertN 'byte-opcode-invert 'insert)
 
-(byte-defop-compiler (dot byte-point)          0)
-(byte-defop-compiler (dot-max byte-point-max)  0)
-(byte-defop-compiler (dot-min byte-point-min)  0)
 (byte-defop-compiler point             0)
 ;;(byte-defop-compiler mark            0) ;; obsolete
 (byte-defop-compiler point-max         0)
@@ -2906,7 +3014,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 (byte-defop-compiler char-after                0-1)
 (byte-defop-compiler set-buffer                1)
 ;;(byte-defop-compiler set-mark                1) ;; obsolete
-(byte-defop-compiler19 forward-word    1)
+(byte-defop-compiler19 forward-word    0-1)
 (byte-defop-compiler19 char-syntax     1)
 (byte-defop-compiler19 nreverse                1)
 (byte-defop-compiler19 car-safe                1)
@@ -2964,7 +3072,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 \f
 (defun byte-compile-subr-wrong-args (form n)
   (byte-compile-set-symbol-position (car form))
-  (byte-compile-warn "%s called with %d arg%s, but requires %s"
+  (byte-compile-warn "`%s' called with %d arg%s, but requires %s"
                     (car form) (length (cdr form))
                     (if (= 1 (length (cdr form))) "" "s") n)
   ;; get run-time wrong-number-of-args error.
@@ -3042,6 +3150,9 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 \f
 ;; more complicated compiler macros
 
+(byte-defop-compiler char-before)
+(byte-defop-compiler backward-char)
+(byte-defop-compiler backward-word)
 (byte-defop-compiler list)
 (byte-defop-compiler concat)
 (byte-defop-compiler fset)
@@ -3053,6 +3164,34 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 (byte-defop-compiler19 (/ byte-quo) byte-compile-quo)
 (byte-defop-compiler19 nconc)
 
+(defun byte-compile-char-before (form)
+  (cond ((= 2 (length form))
+        (byte-compile-form (list 'char-after (if (numberp (nth 1 form))
+                                                 (1- (nth 1 form))
+                                               `(1- ,(nth 1 form))))))
+       ((= 1 (length form))
+        (byte-compile-form '(char-after (1- (point)))))
+       (t (byte-compile-subr-wrong-args form "0-1"))))
+
+;; backward-... ==> forward-... with negated argument.
+(defun byte-compile-backward-char (form)
+  (cond ((= 2 (length form))
+        (byte-compile-form (list 'forward-char (if (numberp (nth 1 form))
+                                                   (- (nth 1 form))
+                                                 `(- ,(nth 1 form))))))
+       ((= 1 (length form))
+        (byte-compile-form '(forward-char -1)))
+       (t (byte-compile-subr-wrong-args form "0-1"))))
+
+(defun byte-compile-backward-word (form)
+  (cond ((= 2 (length form))
+        (byte-compile-form (list 'forward-word (if (numberp (nth 1 form))
+                                                   (- (nth 1 form))
+                                                 `(- ,(nth 1 form))))))
+       ((= 1 (length form))
+        (byte-compile-form '(forward-word -1)))
+       (t (byte-compile-subr-wrong-args form "0-1"))))
+
 (defun byte-compile-list (form)
   (let ((count (length (cdr form))))
     (cond ((= count 0)
@@ -3130,7 +3269,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
          (if (and (consp (car body))
                   (not (eq 'byte-code (car (car body)))))
              (byte-compile-warn
-      "A quoted lambda form is the second argument of fset.  This is probably
+      "A quoted lambda form is the second argument of `fset'.  This is probably
      not what you want, as that lambda cannot be compiled.  Consider using
      the syntax (function (lambda (...) ...)) instead.")))))
   (byte-compile-two-args form))
@@ -3301,11 +3440,14 @@ If FORM is a lambda or a macro, byte-compile it as a function."
 
 (defmacro byte-compile-maybe-guarded (condition &rest body)
   "Execute forms in BODY, potentially guarded by CONDITION.
-CONDITION is the test in an `if' form or in a `cond' clause.
-BODY is to compile the first arm of the if or the body of the
-cond clause.  If CONDITION is of the form `(foundp 'foo)'
-or `(boundp 'foo)', the relevant warnings from BODY about foo
-being undefined will be suppressed."
+CONDITION is a variable whose value is a test in an `if' or `cond'.
+BODY is the code to compile  first arm of the if or the body of the
+cond clause.  If CONDITION's value is of the form (fboundp 'foo)
+or (boundp 'foo), the relevant warnings from BODY about foo's
+being undefined will be suppressed.
+
+If CONDITION's value is (not (featurep 'emacs)) or (featurep 'xemacs),
+that suppresses all warnings during execution of BODY."
   (declare (indent 1) (debug t))
   `(let* ((fbound
           (if (eq 'fboundp (car-safe ,condition))
@@ -3323,13 +3465,19 @@ being undefined will be suppressed."
          (byte-compile-bound-variables
           (if bound
               (cons bound byte-compile-bound-variables)
-            byte-compile-bound-variables)))
-     (progn ,@body)
-     ;; Maybe remove the function symbol from the unresolved list.
-     (if fbound
-        (setq byte-compile-unresolved-functions
-              (delq (assq fbound byte-compile-unresolved-functions)
-                    byte-compile-unresolved-functions)))))
+            byte-compile-bound-variables))
+         ;; Suppress all warnings, for code not used in Emacs.
+         (byte-compile-warnings
+          (if (member ,condition '((featurep 'xemacs)
+                                   (not (featurep 'emacs))))
+              nil byte-compile-warnings)))
+     (unwind-protect
+        (progn ,@body)
+       ;; Maybe remove the function symbol from the unresolved list.
+       (if fbound
+          (setq byte-compile-unresolved-functions
+                (delq (assq fbound byte-compile-unresolved-functions)
+                      byte-compile-unresolved-functions))))))
 
 (defun byte-compile-if (form)
   (byte-compile-form (car (cdr form)))
@@ -3350,7 +3498,8 @@ being undefined will be suppressed."
          (byte-compile-form (nth 2 form) for-effect))
        (byte-compile-goto 'byte-goto donetag)
        (byte-compile-out-tag elsetag)
-       (byte-compile-body (cdr (cdr (cdr form))) for-effect)
+       (byte-compile-maybe-guarded (list 'not clause)
+         (byte-compile-body (cdr (cdr (cdr form))) for-effect))
        (byte-compile-out-tag donetag))))
   (setq for-effect nil))
 
@@ -3370,19 +3519,20 @@ being undefined will be suppressed."
             (if (null (cdr clause))
                 ;; First clause is a singleton.
                 (byte-compile-goto-if t for-effect donetag)
-                (setq nexttag (byte-compile-make-tag))
-                (byte-compile-goto 'byte-goto-if-nil nexttag)
-                (byte-compile-maybe-guarded (car clause)
-                  (byte-compile-body (cdr clause) for-effect))
-                (byte-compile-goto 'byte-goto donetag)
-                (byte-compile-out-tag nexttag)))))
+              (setq nexttag (byte-compile-make-tag))
+              (byte-compile-goto 'byte-goto-if-nil nexttag)
+              (byte-compile-maybe-guarded (car clause)
+                (byte-compile-body (cdr clause) for-effect))
+              (byte-compile-goto 'byte-goto donetag)
+              (byte-compile-out-tag nexttag)))))
     ;; Last clause
-    (and (cdr clause) (not (eq (car clause) t))
-        (progn (byte-compile-maybe-guarded (car clause)
-                                           (byte-compile-form (car clause)))
-               (byte-compile-goto-if nil for-effect donetag)
-               (setq clause (cdr clause))))
-    (byte-compile-body-do-effect clause)
+    (let ((guard (car clause)))
+      (and (cdr clause) (not (eq guard t))
+          (progn (byte-compile-form guard)
+                 (byte-compile-goto-if nil for-effect donetag)
+                 (setq clause (cdr clause))))
+      (byte-compile-maybe-guarded guard
+       (byte-compile-body-do-effect clause)))
     (byte-compile-out-tag donetag)))
 
 (defun byte-compile-and (form)
@@ -3390,24 +3540,38 @@ being undefined will be suppressed."
        (args (cdr form)))
     (if (null args)
        (byte-compile-form-do-effect t)
-      (while (cdr args)
-       (byte-compile-form (car args))
+      (byte-compile-and-recursion args failtag))))
+
+;; Handle compilation of a nontrivial `and' call.
+;; We use tail recursion so we can use byte-compile-maybe-guarded.
+(defun byte-compile-and-recursion (rest failtag)
+  (if (cdr rest)
+      (progn
+       (byte-compile-form (car rest))
        (byte-compile-goto-if nil for-effect failtag)
-       (setq args (cdr args)))
-      (byte-compile-form-do-effect (car args))
-      (byte-compile-out-tag failtag))))
+       (byte-compile-maybe-guarded (car rest)
+         (byte-compile-and-recursion (cdr rest) failtag)))
+    (byte-compile-form-do-effect (car rest))
+    (byte-compile-out-tag failtag)))
 
 (defun byte-compile-or (form)
   (let ((wintag (byte-compile-make-tag))
        (args (cdr form)))
     (if (null args)
        (byte-compile-form-do-effect nil)
-      (while (cdr args)
-       (byte-compile-form (car args))
+      (byte-compile-or-recursion args wintag))))
+
+;; Handle compilation of a nontrivial `or' call.
+;; We use tail recursion so we can use byte-compile-maybe-guarded.
+(defun byte-compile-or-recursion (rest wintag)
+  (if (cdr rest)
+      (progn
+       (byte-compile-form (car rest))
        (byte-compile-goto-if t for-effect wintag)
-       (setq args (cdr args)))
-      (byte-compile-form-do-effect (car args))
-      (byte-compile-out-tag wintag))))
+       (byte-compile-maybe-guarded (list 'not (car rest))
+         (byte-compile-or-recursion (cdr rest) wintag)))
+    (byte-compile-form-do-effect (car rest))
+    (byte-compile-out-tag wintag)))
 
 (defun byte-compile-while (form)
   (let ((endtag (byte-compile-make-tag))
@@ -3512,7 +3676,7 @@ being undefined will be suppressed."
     (byte-compile-set-symbol-position 'condition-case)
     (unless (symbolp var)
       (byte-compile-warn
-       "%s is not a variable-name or nil (in condition-case)" var))
+       "`%s' is not a variable-name or nil (in condition-case)" var))
     (byte-compile-push-constant var)
     (byte-compile-push-constant (byte-compile-top-level
                                 (nth 2 form) for-effect))
@@ -3530,13 +3694,13 @@ being undefined will be suppressed."
                                   (setq syms (cdr syms)))
                                 ok))))
                  (byte-compile-warn
-                   "%s is not a condition name or list of such (in condition-case)"
+                   "`%s' is not a condition name or list of such (in condition-case)"
                    (prin1-to-string condition)))
 ;;                ((not (or (eq condition 't)
 ;;                       (and (stringp (get condition 'error-message))
 ;;                            (consp (get condition 'error-conditions)))))
 ;;                 (byte-compile-warn
-;;                   "%s is not a known condition name (in condition-case)"
+;;                   "`%s' is not a known condition name (in condition-case)"
 ;;                   condition))
                )
          (setq compiled-clauses
@@ -3583,7 +3747,6 @@ being undefined will be suppressed."
 (byte-defop-compiler-1 defconst byte-compile-defvar)
 (byte-defop-compiler-1 autoload)
 (byte-defop-compiler-1 lambda byte-compile-lambda-form)
-(byte-defop-compiler-1 defalias)
 
 (defun byte-compile-defun (form)
   ;; This is not used for file-level defuns with doc strings.
@@ -3597,7 +3760,7 @@ being undefined will be suppressed."
         (list 'fset
               (list 'quote (nth 1 form))
               (byte-compile-byte-code-maker
-               (byte-compile-lambda (cons 'lambda (cdr (cdr form)))))))
+               (byte-compile-lambda (cdr (cdr form)) t))))
        (byte-compile-discard))
     ;; We prefer to generate a defalias form so it will record the function
     ;; definition just like interpreting a defun.
@@ -3605,7 +3768,7 @@ being undefined will be suppressed."
      (list 'defalias
           (list 'quote (nth 1 form))
           (byte-compile-byte-code-maker
-           (byte-compile-lambda (cons 'lambda (cdr (cdr form))))))
+           (byte-compile-lambda (cdr (cdr form)) t)))
      t))
   (byte-compile-constant (nth 1 form)))
 
@@ -3614,8 +3777,7 @@ being undefined will be suppressed."
   (byte-compile-body-do-effect
    (list (list 'fset (list 'quote (nth 1 form))
               (let ((code (byte-compile-byte-code-maker
-                           (byte-compile-lambda
-                            (cons 'lambda (cdr (cdr form)))))))
+                           (byte-compile-lambda (cdr (cdr form)) t))))
                 (if (eq (car-safe code) 'make-byte-code)
                     (list 'cons ''macro code)
                   (list 'quote (cons 'macro (eval code))))))
@@ -3632,7 +3794,7 @@ being undefined will be suppressed."
              (and (eq fun 'defconst) (null (cddr form))))
       (let ((ncall (length (cdr form))))
        (byte-compile-warn
-        "%s called with %d argument%s, but %s %s"
+        "`%s' called with %d argument%s, but %s %s"
         fun ncall
         (if (= 1 ncall) "" "s")
         (if (< ncall 2) "requires" "accepts only")
@@ -3649,7 +3811,7 @@ being undefined will be suppressed."
        `(push ',var current-load-list))
       (when (> (length form) 3)
        (when (and string (not (stringp string)))
-         (byte-compile-warn "third arg to %s %s is not a string: %s"
+         (byte-compile-warn "third arg to `%s %s' is not a string: %s"
                             fun var string))
        `(put ',var 'variable-documentation ,string))
       (if (cddr form)          ; `value' provided
@@ -3685,23 +3847,31 @@ being undefined will be suppressed."
   (error "`lambda' used as function name is invalid"))
 
 ;; Compile normally, but deal with warnings for the function being defined.
-(defun byte-compile-defalias (form)
+(put 'defalias 'byte-hunk-handler 'byte-compile-file-form-defalias)
+(defun byte-compile-file-form-defalias (form)
   (if (and (consp (cdr form)) (consp (nth 1 form))
           (eq (car (nth 1 form)) 'quote)
           (consp (cdr (nth 1 form)))
-          (symbolp (nth 1 (nth 1 form)))
-          (consp (nthcdr 2 form))
-          (consp (nth 2 form))
-          (eq (car (nth 2 form)) 'quote)
-          (consp (cdr (nth 2 form)))
-          (symbolp (nth 1 (nth 2 form))))
-      (progn
+          (symbolp (nth 1 (nth 1 form))))
+      (let ((constant
+            (and (consp (nthcdr 2 form))
+                 (consp (nth 2 form))
+                 (eq (car (nth 2 form)) 'quote)
+                 (consp (cdr (nth 2 form)))
+                 (symbolp (nth 1 (nth 2 form))))))
        (byte-compile-defalias-warn (nth 1 (nth 1 form)))
-       (setq byte-compile-function-environment
-             (cons (cons (nth 1 (nth 1 form))
-                         (nth 1 (nth 2 form)))
-                   byte-compile-function-environment))))
-  (byte-compile-normal-call form))
+       (push (cons (nth 1 (nth 1 form))
+                   (if constant (nth 1 (nth 2 form)) t))
+             byte-compile-function-environment)))
+  ;; We used to jus do: (byte-compile-normal-call form)
+  ;; But it turns out that this fails to optimize the code.
+  ;; So instead we now do the same as what other byte-hunk-handlers do,
+  ;; which is to call back byte-compile-file-form and then return nil.
+  ;; Except that we can't just call byte-compile-file-form since it would
+  ;; call us right back.
+  (byte-compile-keep-pending form)
+  ;; Return nil so the form is not output twice.
+  nil)
 
 ;; Turn off warnings about prior calls to the function being defalias'd.
 ;; This could be smarter and compare those calls with
@@ -3715,7 +3885,21 @@ being undefined will be suppressed."
 (byte-defop-compiler-1 with-no-warnings byte-compile-no-warnings)
 (defun byte-compile-no-warnings (form)
   (let (byte-compile-warnings)
-    (byte-compile-form (cadr form))))
+    (byte-compile-form (cons 'progn (cdr form)))))
+
+;; Warn about misuses of make-variable-buffer-local.
+(byte-defop-compiler-1 make-variable-buffer-local byte-compile-make-variable-buffer-local)
+(defun byte-compile-make-variable-buffer-local (form)
+  (if (and (eq (car-safe (car-safe (cdr-safe form))) 'quote)
+           (memq 'make-local byte-compile-warnings))
+      (byte-compile-warn
+       "`make-variable-buffer-local' should be called at toplevel"))
+  (byte-compile-normal-call form))
+(put 'make-variable-buffer-local
+     'byte-hunk-handler 'byte-compile-form-make-variable-buffer-local)
+(defun byte-compile-form-make-variable-buffer-local (form)
+  (byte-compile-keep-pending form 'byte-compile-normal-call))
+
 \f
 ;;; tags
 
@@ -3883,15 +4067,18 @@ invoked interactively."
                                 (mapconcat 'symbol-name callers ", ")
                               "<top level>"))
              (let ((fill-prefix "    "))
-               (fill-region-as-paragraph p (point)))))
+               (fill-region-as-paragraph p (point)))
+              (unless (= 0 (current-column))
+                (insert "\n"))))
        (if calls
            (progn
              (insert "  calls:\n")
              (setq p (point))
              (insert "    " (mapconcat 'symbol-name calls ", "))
              (let ((fill-prefix "    "))
-               (fill-region-as-paragraph p (point)))))
-       (insert "\n")
+               (fill-region-as-paragraph p (point)))
+              (unless (= 0 (current-column))
+                (insert "\n"))))
        (setq rest (cdr rest)))
 
       (message "Generating call tree...(finding uncalled functions...)")
@@ -3900,7 +4087,7 @@ invoked interactively."
        (while rest
          (or (nth 1 (car rest))
              (null (setq f (car (car rest))))
-             (byte-compile-fdefinition f t)
+             (functionp (byte-compile-fdefinition f t))
              (commandp (byte-compile-fdefinition f nil))
              (setq uncalled (cons f uncalled)))
          (setq rest (cdr rest)))
@@ -3965,33 +4152,39 @@ already up-to-date."
     (kill-emacs (if error 1 0))))
 
 (defun batch-byte-compile-file (file)
-  (condition-case err
+  (if debug-on-error
       (byte-compile-file file)
-    (file-error
-     (message (if (cdr err)
-                 ">>Error occurred processing %s: %s (%s)"
+    (condition-case err
+       (byte-compile-file file)
+      (file-error
+       (message (if (cdr err)
+                   ">>Error occurred processing %s: %s (%s)"
                  ">>Error occurred processing %s: %s")
-             file
-             (get (car err) 'error-message)
-             (prin1-to-string (cdr err)))
-     (let ((destfile (byte-compile-dest-file file)))
-       (if (file-exists-p destfile)
-          (delete-file destfile)))
-     nil)
-    (error
-     (message (if (cdr err)
-                 ">>Error occurred processing %s: %s (%s)"
+               file
+               (get (car err) 'error-message)
+               (prin1-to-string (cdr err)))
+       (let ((destfile (byte-compile-dest-file file)))
+        (if (file-exists-p destfile)
+            (delete-file destfile)))
+       nil)
+      (error
+       (message (if (cdr err)
+                   ">>Error occurred processing %s: %s (%s)"
                  ">>Error occurred processing %s: %s")
-             file
-             (get (car err) 'error-message)
-             (prin1-to-string (cdr err)))
-     nil)))
+               file
+               (get (car err) 'error-message)
+               (prin1-to-string (cdr err)))
+       nil))))
 
 ;;;###autoload
-(defun batch-byte-recompile-directory ()
+(defun batch-byte-recompile-directory (&optional arg)
   "Run `byte-recompile-directory' on the dirs remaining on the command line.
 Must be used only with `-batch', and kills Emacs on completion.
-For example, invoke `emacs -batch -f batch-byte-recompile-directory .'."
+For example, invoke `emacs -batch -f batch-byte-recompile-directory .'.
+
+Optional argument ARG is passed as second argument ARG to
+`batch-recompile-directory'; see there for its possible values
+and corresponding effects."
   ;; command-line-args-left is what is left of the command line (startup.el)
   (defvar command-line-args-left)      ;Avoid 'free variable' warning
   (if (not noninteractive)
@@ -3999,31 +4192,10 @@ For example, invoke `emacs -batch -f batch-byte-recompile-directory .'."
   (or command-line-args-left
       (setq command-line-args-left '(".")))
   (while command-line-args-left
-    (byte-recompile-directory (car command-line-args-left))
+    (byte-recompile-directory (car command-line-args-left) arg)
     (setq command-line-args-left (cdr command-line-args-left)))
   (kill-emacs 0))
 
-
-(make-obsolete-variable 'auto-fill-hook 'auto-fill-function "before 19.15")
-(make-obsolete-variable 'blink-paren-hook 'blink-paren-function "before 19.15")
-(make-obsolete-variable 'lisp-indent-hook 'lisp-indent-function "before 19.15")
-(make-obsolete-variable 'inhibit-local-variables
-               "use enable-local-variables (with the reversed sense)."
-               "before 19.15")
-(make-obsolete-variable 'unread-command-event
-  "use unread-command-events; which is a list of events rather than a single event."
-  "before 19.15")
-(make-obsolete-variable 'suspend-hooks 'suspend-hook "before 19.15")
-(make-obsolete-variable 'comment-indent-hook 'comment-indent-function "before 19.15")
-(make-obsolete-variable 'meta-flag "use the set-input-mode function instead." "before 19.34")
-(make-obsolete-variable 'before-change-function
-  "use before-change-functions; which is a list of functions rather than a single function."
-  "before 19.34")
-(make-obsolete-variable 'after-change-function
-  "use after-change-functions; which is a list of functions rather than a single function."
-  "before 19.34")
-(make-obsolete-variable 'font-lock-doc-string-face 'font-lock-string-face "before 19.34")
-
 (provide 'byte-compile)
 (provide 'bytecomp)
 
@@ -4080,5 +4252,5 @@ For example, invoke `emacs -batch -f batch-byte-recompile-directory .'."
 
 (run-hooks 'bytecomp-load-hook)
 
-;;; arch-tag: 9c97b0f0-8745-4571-bfc3-8dceb677292a
+;; arch-tag: 9c97b0f0-8745-4571-bfc3-8dceb677292a
 ;;; bytecomp.el ends here