]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/bytecomp.el
(byte-compile-maybe-guarded): Restore code commented out 2007-11-10.
[gnu-emacs] / lisp / emacs-lisp / bytecomp.el
index 286725f99c102662da6d980a6590697263e03ac9..064a7aeb76867db29fdae74291481e007a346dff 100644 (file)
@@ -1,7 +1,7 @@
 ;;; bytecomp.el --- compilation of Lisp code into byte code
 
 ;; Copyright (C) 1985, 1986, 1987, 1992, 1994, 1998, 2000, 2001, 2002,
-;;   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
 ;;     Hallvard Furuseth <hbf@ulrik.uio.no>
 ;;                                                not good to call from Lisp)
 ;;                             `make-local' (dubious calls to
 ;;                                           `make-variable-buffer-local')
+;;                              `mapcar'     (mapcar called for effect)
 ;; byte-compile-compatibility  Whether the compiler should
 ;;                             generate .elc files which can be loaded into
 ;;                             generic emacs 18.
@@ -340,7 +341,8 @@ If it is 'byte, then only byte-level optimizations will be logged."
 
 (defconst byte-compile-warning-types
   '(redefine callargs free-vars unresolved
-            obsolete noruntime cl-functions interactive-only)
+            obsolete noruntime cl-functions interactive-only
+            make-local mapcar)
   "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).
@@ -359,7 +361,11 @@ Elements of the list may be:
                  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."
+  make-local  calls to make-variable-buffer-local that may be incorrect.
+  mapcar      mapcar called for effect.
+
+If the list begins with `not', then the remaining elements specify warnings to
+suppress.  For example, (not mapcar) will suppress warnings about mapcar."
   :group 'bytecomp
   :type `(choice (const :tag "All" t)
                 (set :menu-tag "Some"
@@ -367,25 +373,69 @@ Elements of the list may be:
                      (const callargs) (const redefine)
                      (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)
+                     (const make-local) (const mapcar))))
+;;;###autoload(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)
+           (if (eq (car x) 'not) (setq x (cdr x))
+             t)
           (equal (mapcar
                   (lambda (e)
                     (when (memq e '(free-vars unresolved
                                     callargs redefine
                                     obsolete noruntime
-                                    cl-functions interactive-only make-local))
+                                    cl-functions interactive-only
+                                    make-local mapcar))
                       e))
                   x)
                  x))))
 
+(defun byte-compile-warning-enabled-p (warning)
+  "Return non-nil if WARNING is enabled, according to `byte-compile-warnings'."
+  (or (eq byte-compile-warnings t)
+      (if (eq (car byte-compile-warnings) 'not)
+          (not (memq warning byte-compile-warnings))
+        (memq warning byte-compile-warnings))))
+
+;;;###autoload
+(defun byte-compile-disable-warning (warning)
+  "Change `byte-compile-warnings' to disable WARNING.
+If `byte-compile-warnings' is t, set it to `(not WARNING)'.
+Otherwise, if the first element is `not', add WARNING, else remove it.
+Normally you should let-bind `byte-compile-warnings' before calling this,
+else the global value will be modified."
+  (setq byte-compile-warnings
+        (cond ((eq byte-compile-warnings t)
+               (list 'not warning))
+              ((eq (car byte-compile-warnings) 'not)
+               (if (memq warning byte-compile-warnings)
+                   byte-compile-warnings
+                 (append byte-compile-warnings (list warning))))
+              (t
+               (delq warning byte-compile-warnings)))))
+
+;;;###autoload
+(defun byte-compile-enable-warning (warning)
+  "Change `byte-compile-warnings' to enable WARNING.
+If `byte-compile-warnings' is `t', do nothing.  Otherwise, if the
+first element is `not', remove WARNING, else add it.
+Normally you should let-bind `byte-compile-warnings' before calling this,
+else the global value will be modified."
+  (or (eq byte-compile-warnings t)
+      (setq byte-compile-warnings
+            (cond ((eq (car byte-compile-warnings) 'not)
+                   (delq warning byte-compile-warnings))
+                  ((memq warning byte-compile-warnings)
+                   byte-compile-warnings)
+                  (t
+                   (append byte-compile-warnings (list warning)))))))
+
 (defvar byte-compile-interactive-only-functions
   '(beginning-of-buffer end-of-buffer replace-string replace-regexp
-    insert-file insert-buffer insert-file-literally)
+    insert-file insert-buffer insert-file-literally previous-line next-line)
   "List of commands that are not meant to be called from Lisp.")
 
 (defvar byte-compile-not-obsolete-var nil
@@ -814,7 +864,7 @@ otherwise pop it")
               (setcar (cdr bytes) (logand pc 255))
               (setcar bytes (lsh pc -8))))
        (setq patchlist (cdr patchlist))))
-    (concat (nreverse bytes))))
+    (apply 'unibyte-string (nreverse bytes))))
 
 \f
 ;;; compile-time evaluation
@@ -825,7 +875,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
   (let ((hist-orig load-history)
        (hist-nil-orig current-load-list))
     (prog1 (eval form)
-      (when (memq 'noruntime byte-compile-warnings)
+      (when (byte-compile-warning-enabled-p 'noruntime)
        (let ((hist-new load-history)
              (hist-nil-new current-load-list))
          ;; Go through load-history, look for newly loaded files
@@ -853,7 +903,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
                  (push s byte-compile-noruntime-functions))
                (when (and (consp s) (eq t (car s)))
                  (push (cdr s) old-autoloads)))))))
-      (when (memq 'cl-functions byte-compile-warnings)
+      (when (byte-compile-warning-enabled-p 'cl-functions)
        (let ((hist-new load-history))
          ;; Go through load-history, look for newly loaded files
          ;; and mark all the functions defined therein.
@@ -871,8 +921,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
       (let ((tem current-load-list))
        (while (not (eq tem hist-nil-orig))
          (when (equal (car tem) '(require . cl))
-           (setq byte-compile-warnings
-                 (remq 'cl-functions byte-compile-warnings)))
+            (byte-compile-disable-warning 'cl-functions))
          (setq tem (cdr tem)))))))
 \f
 ;;; byte compiler messages
@@ -975,7 +1024,7 @@ 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:" 
+                   (format "%d:%d:"
                            (save-excursion
                              (goto-char byte-compile-last-position)
                              (1+ (count-lines (point-min) (point-at-bol))))
@@ -1004,14 +1053,16 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 (defun byte-compile-warning-series (&rest ignore)
   nil)
 
+;; (compile-mode) will cause this to be loaded.
+(declare-function compilation-forget-errors "compile" ())
+
 ;; Log the start of a file in *Compile-Log*, and mark it as done.
 ;; Return the position of the start of the page in the log buffer.
 ;; But do nothing in batch mode.
 (defun byte-compile-log-file ()
   (and (not (equal byte-compile-current-file byte-compile-last-logged-file))
        (not noninteractive)
-       (save-excursion
-        (set-buffer (get-buffer-create "*Compile-Log*"))
+       (with-current-buffer (get-buffer-create "*Compile-Log*")
         (goto-char (point-max))
         (let* ((inhibit-read-only t)
                (dir (and byte-compile-current-file
@@ -1038,8 +1089,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
           (setq byte-compile-last-logged-file byte-compile-current-file
                 byte-compile-last-warned-form nil)
           ;; Do this after setting default-directory.
-          (unless (eq major-mode 'compilation-mode)
-            (compilation-mode))
+          (unless (derived-mode-p 'compilation-mode) (compilation-mode))
           (compilation-forget-errors)
           pt))))
 
@@ -1072,7 +1122,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
         (handler (nth 1 new))
         (when (nth 2 new)))
     (byte-compile-set-symbol-position (car form))
-    (if (memq 'obsolete byte-compile-warnings)
+    (if (byte-compile-warning-enabled-p 'obsolete)
        (byte-compile-warn "`%s' is an obsolete function%s; %s" (car form)
                           (if when (concat " (as of Emacs " when ")") "")
                           (if (stringp (car new))
@@ -1211,7 +1261,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
                  (byte-compile-fdefinition (car form) t)))
         (sig (if (and def (not (eq def t)))
                  (byte-compile-arglist-signature
-                  (if (eq 'lambda (car-safe def))
+                  (if (memq (car-safe def) '(declared lambda))
                       (nth 1 def)
                     (if (byte-code-function-p def)
                         (aref def 0)
@@ -1418,7 +1468,7 @@ extra args."
 ;; defined, issue a warning enumerating them.
 ;; `unresolved' in the list `byte-compile-warnings' disables this.
 (defun byte-compile-warn-about-unresolved-functions ()
-  (when (memq 'unresolved byte-compile-warnings)
+  (when (byte-compile-warning-enabled-p 'unresolved)
     (let ((byte-compile-current-form :end)
          (noruntime nil)
          (unresolved nil))
@@ -1481,9 +1531,7 @@ symbol itself."
                 byte-compile-dynamic-docstrings)
 ;;             (byte-compile-generate-emacs19-bytecodes
 ;;              byte-compile-generate-emacs19-bytecodes)
-               (byte-compile-warnings (if (eq byte-compile-warnings t)
-                                          byte-compile-warning-types
-                                        byte-compile-warnings))
+               (byte-compile-warnings byte-compile-warnings)
                )
              body)))
 
@@ -1548,13 +1596,12 @@ recompile every `.el' file that already has a `.elc' file."
       nil
     (save-some-buffers)
     (force-mode-line-update))
-  (save-current-buffer
-    (set-buffer (get-buffer-create "*Compile-Log*"))
+  (with-current-buffer (get-buffer-create "*Compile-Log*")
     (setq default-directory (expand-file-name directory))
     ;; compilation-mode copies value of default-directory.
     (unless (eq major-mode 'compilation-mode)
       (compilation-mode))
-    (let ((directories (list (expand-file-name directory)))
+    (let ((directories (list default-directory))
          (default-directory default-directory)
          (skip-count 0)
          (fail-count 0)
@@ -1651,7 +1698,7 @@ The value is non-nil if there were no errors, nil if errors."
       (let ((b (get-file-buffer (expand-file-name filename))))
        (if (and b (buffer-modified-p b)
                 (y-or-n-p (format "Save buffer %s first? " (buffer-name b))))
-           (save-excursion (set-buffer b) (save-buffer)))))
+           (with-current-buffer b (save-buffer)))))
 
   ;; Force logging of the file name for each file compiled.
   (setq byte-compile-last-logged-file nil)
@@ -1661,9 +1708,8 @@ The value is non-nil if there were no errors, nil if errors."
        byte-compile-dest-file)
     (setq target-file (byte-compile-dest-file filename))
     (setq byte-compile-dest-file target-file)
-    (save-excursion
-      (setq input-buffer (get-buffer-create " *Compiler Input*"))
-      (set-buffer input-buffer)
+    (with-current-buffer
+        (setq input-buffer (get-buffer-create " *Compiler Input*"))
       (erase-buffer)
       (setq buffer-file-coding-system nil)
       ;; Always compile an Emacs Lisp file as multibyte
@@ -1828,9 +1874,7 @@ With argument, insert value in current buffer after the form."
        (read-with-symbol-positions inbuffer)
        (read-symbol-positions-list nil)
        ;;        #### This is bound in b-c-close-variables.
-       ;;        (byte-compile-warnings (if (eq byte-compile-warnings t)
-       ;;                                   byte-compile-warning-types
-       ;;                                 byte-compile-warnings))
+       ;;        (byte-compile-warnings byte-compile-warnings)
        )
     (byte-compile-close-variables
      (with-current-buffer
@@ -1864,7 +1908,13 @@ With argument, insert value in current buffer after the form."
                 (not (eobp)))
          (setq byte-compile-read-position (point)
                byte-compile-last-position byte-compile-read-position)
-         (let ((form (read inbuffer)))
+         (let* ((old-style-backquotes nil)
+                 (form (read inbuffer)))
+            ;; Warn about the use of old-style backquotes.
+            (when old-style-backquotes
+              (byte-compile-warn "!! The file uses old-style backquotes !!
+This functionality has been obsolete for more than 10 years already
+and will be removed soon.  See (elisp)Backquote in the manual."))
            (byte-compile-file-form form)))
        ;; Compile pending forms at end of file.
        (byte-compile-flush-pending)
@@ -1899,13 +1949,13 @@ With argument, insert value in current buffer after the form."
        (delete-region (point) (progn (re-search-forward "^(")
                                      (beginning-of-line)
                                      (point)))
-       (insert ";;; This file contains multibyte non-ASCII characters\n"
-               ";;; and therefore cannot be loaded into Emacs 19.\n")
-       ;; Replace "19" or "19.29" with "20", twice.
+       (insert ";;; This file contains utf-8 non-ASCII characters\n"
+               ";;; and therefore cannot be loaded into Emacs 21 or earlier.\n")
+       ;; Replace "19" or "19.29" with "22", twice.
        (re-search-forward "19\\(\\.[0-9]+\\)")
-       (replace-match "20")
+       (replace-match "23")
        (re-search-forward "19\\(\\.[0-9]+\\)")
-       (replace-match "20")
+       (replace-match "23")
        ;; Now compensate for the change in size,
        ;; to make sure all positions in the file remain valid.
        (setq delta (- (point-max) old-header-end))
@@ -1914,52 +1964,52 @@ With argument, insert value in current buffer after the form."
        (delete-char delta)))))
 
 (defun byte-compile-insert-header (filename inbuffer outbuffer)
-  (set-buffer inbuffer)
-  (let ((dynamic-docstrings byte-compile-dynamic-docstrings)
-       (dynamic byte-compile-dynamic))
-    (set-buffer outbuffer)
-    (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
-    ;; this is to get some binary characters up in the first line of
-    ;; the file so that `diff' will simply say "Binary files differ"
-    ;; instead of actually doing a diff of two .elc files.  An extra
-    ;; benefit is that you can add this to /etc/magic:
-
-    ;; 0       string          ;ELC            GNU Emacs Lisp compiled file,
-    ;; >4      byte            x               version %d
-
-    (insert
-     ";ELC"
-     (if (byte-compile-version-cond byte-compile-compatibility) 18 20)
-     "\000\000\000\n"
-     )
-    (insert ";;; Compiled by "
-           (or (and (boundp 'user-mail-address) user-mail-address)
-               (concat (user-login-name) "@" (system-name)))
-           " on "
-           (current-time-string) "\n;;; from file " filename "\n")
-    (insert ";;; in Emacs version " emacs-version "\n")
-    (insert ";;; "
-           (cond
-            ((eq byte-optimize 'source) "with source-level optimization only")
-            ((eq byte-optimize 'byte) "with byte-level optimization only")
-            (byte-optimize "with all optimizations")
-            (t "without optimization"))
-           (if (byte-compile-version-cond byte-compile-compatibility)
-               "; compiled with Emacs 18 compatibility.\n"
-             ".\n"))
-    (if dynamic
-       (insert ";;; Function definitions are lazy-loaded.\n"))
-    (if (not (byte-compile-version-cond byte-compile-compatibility))
-       (let (intro-string minimum-version)
-         ;; Figure out which Emacs version to require,
-         ;; and what comment to use to explain why.
-         ;; Note that this fails to take account of whether
-         ;; the buffer contains multibyte characters.  We may have to
-         ;; compensate at the end in byte-compile-fix-header.
-         (if dynamic-docstrings
+  (with-current-buffer inbuffer
+    (let ((dynamic-docstrings byte-compile-dynamic-docstrings)
+         (dynamic byte-compile-dynamic))
+      (set-buffer outbuffer)
+      (goto-char (point-min))
+      ;; The magic number of .elc files is ";ELC", or 0x3B454C43.  After
+      ;; that is the file-format version number (18, 19, 20, or 23) as a
+      ;; byte, followed by some nulls.  The primary motivation for doing
+      ;; this is to get some binary characters up in the first line of
+      ;; the file so that `diff' will simply say "Binary files differ"
+      ;; instead of actually doing a diff of two .elc files.  An extra
+      ;; benefit is that you can add this to /etc/magic:
+
+      ;; 0     string          ;ELC            GNU Emacs Lisp compiled file,
+      ;; >4    byte            x               version %d
+
+      (insert
+       ";ELC"
+       (if (byte-compile-version-cond byte-compile-compatibility) 18 23)
+       "\000\000\000\n"
+       )
+      (insert ";;; Compiled by "
+             (or (and (boundp 'user-mail-address) user-mail-address)
+                 (concat (user-login-name) "@" (system-name)))
+             " on "
+             (current-time-string) "\n;;; from file " filename "\n")
+      (insert ";;; in Emacs version " emacs-version "\n")
+      (insert ";;; "
+             (cond
+              ((eq byte-optimize 'source) "with source-level optimization only")
+              ((eq byte-optimize 'byte) "with byte-level optimization only")
+              (byte-optimize "with all optimizations")
+              (t "without optimization"))
+             (if (byte-compile-version-cond byte-compile-compatibility)
+                 "; compiled with Emacs 18 compatibility.\n"
+               ".\n"))
+      (if dynamic
+         (insert ";;; Function definitions are lazy-loaded.\n"))
+      (if (not (byte-compile-version-cond byte-compile-compatibility))
+         (let (intro-string minimum-version)
+           ;; Figure out which Emacs version to require,
+           ;; and what comment to use to explain why.
+           ;; Note that this fails to take account of whether
+           ;; the buffer contains multibyte characters.  We may have to
+           ;; compensate at the end in byte-compile-fix-header.
+           (if dynamic-docstrings
              (setq intro-string
                    ";;; This file uses dynamic docstrings, first added in Emacs 19.29.\n"
                    minimum-version "19.29")
@@ -1988,14 +2038,14 @@ With argument, insert value in current buffer after the form."
           ;; Insert semicolons as ballast, so that byte-compile-fix-header
           ;; can delete them so as to keep the buffer positions
           ;; constant for the actual compiled code.
-          ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n"))
+          ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n"))
       ;; Here if we want Emacs 18 compatibility.
       (when dynamic-docstrings
        (error "Version-18 compatibility doesn't support dynamic doc strings"))
       (when byte-compile-dynamic
        (error "Version-18 compatibility doesn't support dynamic byte code"))
       (insert "(or (boundp 'current-load-list) (setq current-load-list nil))\n"
-             "\n"))))
+               "\n")))))
 
 (defun byte-compile-output-file-form (form)
   ;; writes the given form to the output buffer, being careful of docstrings
@@ -2037,85 +2087,83 @@ list that represents a doc string reference.
   ;; We need to examine byte-compile-dynamic-docstrings
   ;; in the input buffer (now current), not in the output buffer.
   (let ((dynamic-docstrings byte-compile-dynamic-docstrings))
-    (set-buffer
-     (prog1 (current-buffer)
-       (set-buffer outbuffer)
-       (let (position)
-
-        ;; Insert the doc string, and make it a comment with #@LENGTH.
-        (and (>= (nth 1 info) 0)
-             dynamic-docstrings
-             (not byte-compile-compatibility)
-             (progn
-               ;; Make the doc string start at beginning of line
-               ;; for make-docfile's sake.
-               (insert "\n")
-               (setq position
-                     (byte-compile-output-as-comment
-                      (nth (nth 1 info) form) nil))
-               (setq position (- (position-bytes position) (point-min) -1))
-               ;; If the doc string starts with * (a user variable),
-               ;; negate POSITION.
-               (if (and (stringp (nth (nth 1 info) form))
-                        (> (length (nth (nth 1 info) form)) 0)
-                        (eq (aref (nth (nth 1 info) form) 0) ?*))
-                   (setq position (- position)))))
-
-        (if preface
-            (progn
-              (insert preface)
-              (prin1 name outbuffer)))
-        (insert (car info))
-        (let ((print-escape-newlines t)
-              (print-quoted t)
-              ;; For compatibility with code before print-circle,
-              ;; use a cons cell to say that we want
-              ;; 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
-              (index 0))
-          (prin1 (car form) outbuffer)
-          (while (setq form (cdr form))
-            (setq index (1+ index))
-            (insert " ")
-            (cond ((and (numberp specindex) (= index specindex)
-                        ;; Don't handle the definition dynamically
-                        ;; if it refers (or might refer)
-                        ;; to objects already output
-                        ;; (for instance, gensyms in the arg list).
-                        (let (non-nil)
-                          (dotimes (i (length print-number-table))
-                            (if (aref print-number-table i)
-                                (setq non-nil t)))
-                          (not non-nil)))
-                   ;; Output the byte code and constants specially
-                   ;; for lazy dynamic loading.
-                   (let ((position
-                          (byte-compile-output-as-comment
-                           (cons (car form) (nth 1 form))
-                           t)))
-                     (setq position (- (position-bytes position) (point-min) -1))
-                     (princ (format "(#$ . %d) nil" position) outbuffer)
-                     (setq form (cdr form))
-                     (setq index (1+ index))))
-                  ((= index (nth 1 info))
-                   (if position
-                       (princ (format (if quoted "'(#$ . %d)"  "(#$ . %d)")
-                                      position)
-                              outbuffer)
-                     (let ((print-escape-newlines nil))
-                       (goto-char (prog1 (1+ (point))
-                                    (prin1 (car form) outbuffer)))
-                       (insert "\\\n")
-                       (goto-char (point-max)))))
-                  (t
-                   (prin1 (car form) outbuffer)))))
-        (insert (nth 2 info))))))
+    (with-current-buffer outbuffer
+      (let (position)
+
+        ;; Insert the doc string, and make it a comment with #@LENGTH.
+        (and (>= (nth 1 info) 0)
+             dynamic-docstrings
+             (not byte-compile-compatibility)
+             (progn
+               ;; Make the doc string start at beginning of line
+               ;; for make-docfile's sake.
+               (insert "\n")
+               (setq position
+                     (byte-compile-output-as-comment
+                      (nth (nth 1 info) form) nil))
+               (setq position (- (position-bytes position) (point-min) -1))
+               ;; If the doc string starts with * (a user variable),
+               ;; negate POSITION.
+               (if (and (stringp (nth (nth 1 info) form))
+                        (> (length (nth (nth 1 info) form)) 0)
+                        (eq (aref (nth (nth 1 info) form) 0) ?*))
+                   (setq position (- position)))))
+
+        (if preface
+            (progn
+              (insert preface)
+              (prin1 name outbuffer)))
+        (insert (car info))
+        (let ((print-escape-newlines t)
+              (print-quoted t)
+              ;; For compatibility with code before print-circle,
+              ;; use a cons cell to say that we want
+              ;; 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
+              (index 0))
+          (prin1 (car form) outbuffer)
+          (while (setq form (cdr form))
+            (setq index (1+ index))
+            (insert " ")
+            (cond ((and (numberp specindex) (= index specindex)
+                        ;; Don't handle the definition dynamically
+                        ;; if it refers (or might refer)
+                        ;; to objects already output
+                        ;; (for instance, gensyms in the arg list).
+                        (let (non-nil)
+                          (dotimes (i (length print-number-table))
+                            (if (aref print-number-table i)
+                                (setq non-nil t)))
+                          (not non-nil)))
+                   ;; Output the byte code and constants specially
+                   ;; for lazy dynamic loading.
+                   (let ((position
+                          (byte-compile-output-as-comment
+                           (cons (car form) (nth 1 form))
+                           t)))
+                     (setq position (- (position-bytes position) (point-min) -1))
+                     (princ (format "(#$ . %d) nil" position) outbuffer)
+                     (setq form (cdr form))
+                     (setq index (1+ index))))
+                  ((= index (nth 1 info))
+                   (if position
+                       (princ (format (if quoted "'(#$ . %d)"  "(#$ . %d)")
+                                      position)
+                              outbuffer)
+                     (let ((print-escape-newlines nil))
+                       (goto-char (prog1 (1+ (point))
+                                    (prin1 (car form) outbuffer)))
+                       (insert "\\\n")
+                       (goto-char (point-max)))))
+                  (t
+                   (prin1 (car form) outbuffer)))))
+        (insert (nth 2 info)))))
   nil)
 
 (defun byte-compile-keep-pending (form &optional handler)
@@ -2205,7 +2253,7 @@ list that represents a doc string reference.
       ;; Since there is no doc string, we can compile this as a normal form,
       ;; and not do a file-boundary.
       (byte-compile-keep-pending form)
-    (when (memq 'free-vars byte-compile-warnings)
+    (when (byte-compile-warning-enabled-p 'free-vars)
       (push (nth 1 form) byte-compile-bound-variables)
       (if (eq (car form) 'defconst)
          (push (nth 1 form) byte-compile-const-variables)))
@@ -2215,25 +2263,31 @@ list that represents a doc string reference.
                   (byte-compile-top-level (nth 2 form) nil 'file))))
     form))
 
+(put 'define-abbrev-table 'byte-hunk-handler 'byte-compile-file-form-define-abbrev-table)
+(defun byte-compile-file-form-define-abbrev-table (form)
+  (when (and (byte-compile-warning-enabled-p 'free-vars)
+             (eq 'quote (car-safe (car-safe (cdr form)))))
+    (push (car-safe (cdr (cadr form))) byte-compile-bound-variables))
+  (byte-compile-keep-pending form))
+
 (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)
+  (when (byte-compile-warning-enabled-p 'callargs)
     (byte-compile-nogroup-warn form))
-  (when (memq 'free-vars byte-compile-warnings)
+  (when (byte-compile-warning-enabled-p 'free-vars)
     (push (nth 1 (nth 1 form)) byte-compile-bound-variables))
+  ;; Don't compile the expression because it may be displayed to the user.
+  ;; (when (eq (car-safe (nth 2 form)) 'quote)
+  ;;   ;; (nth 2 form) is meant to evaluate to an expression, so if we have the
+  ;;   ;; final value already, we can byte-compile it.
+  ;;   (setcar (cdr (nth 2 form))
+  ;;           (byte-compile-top-level (cadr (nth 2 form)) nil 'file)))
   (let ((tail (nthcdr 4 form)))
     (while tail
-      ;; If there are any (function (lambda ...)) expressions, compile
-      ;; those functions.
-      (if (and (consp (car tail))
-              (eq (car (car tail)) 'function)
-              (consp (nth 1 (car tail))))
-         (setcar tail (byte-compile-lambda (nth 1 (car tail))))
-       ;; Likewise for a bare lambda.
-       (if (and (consp (car tail))
-                (eq (car (car tail)) 'lambda))
-           (setcar tail (byte-compile-lambda (car tail)))))
+      (unless (keywordp (car tail))      ;No point optimizing keywords.
+        ;; Compile the keyword arguments.
+        (setcar tail (byte-compile-top-level (car tail) nil 'file)))
       (setq tail (cdr tail))))
   form)
 
@@ -2243,8 +2297,7 @@ list that represents a doc string reference.
     (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-disable-warning 'cl-functions)))
   (byte-compile-keep-pending form 'byte-compile-normal-call))
 
 (put 'progn 'byte-hunk-handler 'byte-compile-file-form-progn)
@@ -2290,12 +2343,12 @@ list that represents a doc string reference.
                  (cons (list name nil nil) byte-compile-call-tree))))
 
     (setq byte-compile-current-form name) ; for warnings
-    (if (memq 'redefine byte-compile-warnings)
+    (if (byte-compile-warning-enabled-p 'redefine)
        (byte-compile-arglist-warn form macrop))
     (if byte-compile-verbose
        (message "Compiling %s... (%s)" (or filename "") (nth 1 form)))
     (cond (that-one
-          (if (and (memq 'redefine byte-compile-warnings)
+          (if (and (byte-compile-warning-enabled-p 'redefine)
                    ;; don't warn when compiling the stubs in byte-run...
                    (not (assq (nth 1 form)
                               byte-compile-initial-macro-environment)))
@@ -2304,7 +2357,7 @@ list that represents a doc string reference.
                 (nth 1 form)))
           (setcdr that-one nil))
          (this-one
-          (when (and (memq 'redefine byte-compile-warnings)
+          (when (and (byte-compile-warning-enabled-p 'redefine)
                    ;; hack: don't warn when compiling the magic internal
                    ;; byte-compiler macros in byte-run.el...
                    (not (assq (nth 1 form)
@@ -2315,7 +2368,7 @@ list that represents a doc string reference.
          ((and (fboundp name)
                (eq (car-safe (symbol-function name))
                    (if macrop 'lambda 'macro)))
-          (when (memq 'redefine byte-compile-warnings)
+          (when (byte-compile-warning-enabled-p 'redefine)
             (byte-compile-warn "%s `%s' being redefined as a %s"
                                (if macrop "function" "macro")
                                (nth 1 form)
@@ -2401,39 +2454,37 @@ list that represents a doc string reference.
 ;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting.
 (defun byte-compile-output-as-comment (exp quoted)
   (let ((position (point)))
-    (set-buffer
-     (prog1 (current-buffer)
-       (set-buffer outbuffer)
-
-       ;; Insert EXP, and make it a comment with #@LENGTH.
-       (insert " ")
-       (if quoted
-          (prin1 exp outbuffer)
-        (princ exp outbuffer))
-       (goto-char position)
-       ;; Quote certain special characters as needed.
-       ;; get_doc_string in doc.c does the unquoting.
-       (while (search-forward "\^A" nil t)
-        (replace-match "\^A\^A" t t))
-       (goto-char position)
-       (while (search-forward "\000" nil t)
-        (replace-match "\^A0" t t))
-       (goto-char position)
-       (while (search-forward "\037" nil t)
-        (replace-match "\^A_" t t))
-       (goto-char (point-max))
-       (insert "\037")
-       (goto-char position)
-       (insert "#@" (format "%d" (- (position-bytes (point-max))
-                                   (position-bytes position))))
-
-       ;; Save the file position of the object.
-       ;; Note we should add 1 to skip the space
-       ;; that we inserted before the actual doc string,
-       ;; and subtract 1 to convert from an 1-origin Emacs position
-       ;; to a file position; they cancel.
-       (setq position (point))
-       (goto-char (point-max))))
+    (with-current-buffer outbuffer
+
+      ;; Insert EXP, and make it a comment with #@LENGTH.
+      (insert " ")
+      (if quoted
+          (prin1 exp outbuffer)
+        (princ exp outbuffer))
+      (goto-char position)
+      ;; Quote certain special characters as needed.
+      ;; get_doc_string in doc.c does the unquoting.
+      (while (search-forward "\^A" nil t)
+        (replace-match "\^A\^A" t t))
+      (goto-char position)
+      (while (search-forward "\000" nil t)
+        (replace-match "\^A0" t t))
+      (goto-char position)
+      (while (search-forward "\037" nil t)
+        (replace-match "\^A_" t t))
+      (goto-char (point-max))
+      (insert "\037")
+      (goto-char position)
+      (insert "#@" (format "%d" (- (position-bytes (point-max))
+                                   (position-bytes position))))
+
+      ;; Save the file position of the object.
+      ;; Note we should add 1 to skip the space
+      ;; that we inserted before the actual doc string,
+      ;; and subtract 1 to convert from an 1-origin Emacs position
+      ;; to a file position; they cancel.
+      (setq position (point))
+      (goto-char (point-max)))
     position))
 
 
@@ -2557,7 +2608,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
   (byte-compile-check-lambda-list (nth 1 fun))
   (let* ((arglist (nth 1 fun))
         (byte-compile-bound-variables
-         (nconc (and (memq 'free-vars byte-compile-warnings)
+         (nconc (and (byte-compile-warning-enabled-p 'free-vars)
                      (delq '&rest (delq '&optional (copy-sequence arglist))))
                 byte-compile-bound-variables))
         (body (cdr (cdr fun)))
@@ -2768,6 +2819,20 @@ If FORM is a lambda or a macro, byte-compile it as a function."
         (cdr body))
        (body
         (list body))))
+
+(put 'declare-function 'byte-hunk-handler 'byte-compile-declare-function)
+(defun byte-compile-declare-function (form)
+  (push (cons (nth 1 form)
+              (if (and (> (length form) 3)
+                       (listp (nth 3 form)))
+                  (list 'declared (nth 3 form))
+                t))                     ; arglist not specified
+        byte-compile-function-environment)
+  ;; We are stating that it _will_ be defined at runtime.
+  (setq byte-compile-noruntime-functions
+        (delq (nth 1 form) byte-compile-noruntime-functions))
+  nil)
+
 \f
 ;; This is the recursive entry point for compiling each subform of an
 ;; expression.
@@ -2797,7 +2862,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
                (handler (get fn 'byte-compile)))
           (when (byte-compile-const-symbol-p fn)
             (byte-compile-warn "`%s' called as a function" fn))
-          (and (memq 'interactive-only byte-compile-warnings)
+          (and (byte-compile-warning-enabled-p 'interactive-only)
                (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))
@@ -2812,12 +2877,12 @@ That command is designed for interactive use only" fn))
                                byte-compile-compatibility)
                               (get (get fn 'byte-opcode) 'emacs19-opcode))))
                (funcall handler form)
-            (when (memq 'callargs byte-compile-warnings)
+            (when (byte-compile-warning-enabled-p 'callargs)
               (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)
+          (if (byte-compile-warning-enabled-p 'cl-functions)
               (byte-compile-cl-warn form))))
        ((and (or (byte-code-function-p (car form))
                  (eq (car-safe (car form)) 'lambda))
@@ -2833,6 +2898,11 @@ That command is designed for interactive use only" fn))
 (defun byte-compile-normal-call (form)
   (if byte-compile-generate-call-tree
       (byte-compile-annotate-call-tree form))
+  (when (and for-effect (eq (car form) 'mapcar)
+             (byte-compile-warning-enabled-p 'mapcar))
+    (byte-compile-set-symbol-position 'mapcar)
+    (byte-compile-warn
+     "`mapcar' called for effect; use `mapc' or `dolist' instead"))
   (byte-compile-push-constant (car form))
   (mapc 'byte-compile-form (cdr form)) ; wasteful, but faster.
   (byte-compile-out 'byte-call (length (cdr form))))
@@ -2849,7 +2919,7 @@ That command is designed for interactive use only" fn))
        (if (symbolp var) "constant" "nonvariable")
        (prin1-to-string var))
     (if (and (get var 'byte-obsolete-variable)
-            (memq 'obsolete byte-compile-warnings)
+            (byte-compile-warning-enabled-p 'obsolete)
             (not (eq var byte-compile-not-obsolete-var)))
        (let* ((ob (get var 'byte-obsolete-variable))
               (when (cdr ob)))
@@ -2858,7 +2928,7 @@ That command is designed for interactive use only" fn))
                             (if (stringp (car ob))
                                 (car ob)
                               (format "use `%s' instead." (car ob))))))
-    (if (memq 'free-vars byte-compile-warnings)
+    (if (byte-compile-warning-enabled-p 'free-vars)
        (if (eq base-op 'byte-varbind)
            (push var byte-compile-bound-variables)
          (or (boundp var)
@@ -3415,6 +3485,8 @@ That command is designed for interactive use only" fn))
 (byte-defop-compiler-1 mapc byte-compile-funarg)
 (byte-defop-compiler-1 maphash byte-compile-funarg)
 (byte-defop-compiler-1 map-char-table byte-compile-funarg)
+(byte-defop-compiler-1 map-char-table byte-compile-funarg-2)
+;; map-charset-chars should be funarg but has optional third arg
 (byte-defop-compiler-1 sort byte-compile-funarg-2)
 (byte-defop-compiler-1 let)
 (byte-defop-compiler-1 let*)
@@ -3438,6 +3510,32 @@ That command is designed for interactive use only" fn))
       (if ,discard 'byte-goto-if-nil 'byte-goto-if-nil-else-pop))
     ,tag))
 
+;; Return the list of items in CONDITION-PARAM that match PRED-LIST.
+;; Only return items that are not in ONLY-IF-NOT-PRESENT.
+(defun byte-compile-find-bound-condition (condition-param
+                                         pred-list
+                                         &optional only-if-not-present)
+  (let ((result nil)
+       (nth-one nil)
+       (cond-list
+        (if (memq (car-safe condition-param) pred-list)
+            ;; The condition appears by itself.
+            (list condition-param)
+          ;; If the condition is an `and', look for matches among the
+          ;; `and' arguments.
+          (when (eq 'and (car-safe condition-param))
+            (cdr condition-param)))))
+
+    (dolist (crt cond-list)
+      (when (and (memq (car-safe crt) pred-list)
+                (eq 'quote (car-safe (setq nth-one (nth 1 crt))))
+                ;; Ignore if the symbol is already on the unresolved
+                ;; list.
+                (not (assq (nth 1 nth-one) ; the relevant symbol
+                           only-if-not-present)))
+       (push (nth 1 (nth 1 crt)) result)))
+    result))
+
 (defmacro byte-compile-maybe-guarded (condition &rest body)
   "Execute forms in BODY, potentially guarded by CONDITION.
 CONDITION is a variable whose value is a test in an `if' or `cond'.
@@ -3449,35 +3547,40 @@ 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))
-              (and (eq 'quote (car-safe (nth 1 ,condition)))
-                   ;; Ignore if the symbol is already on the
-                   ;; unresolved list.
-                   (not (assq (nth 1 (nth 1 ,condition)) ; the relevant symbol
-                              byte-compile-unresolved-functions))
-                   (nth 1 (nth 1 ,condition)))))
-         (bound (if (or (eq 'boundp (car-safe ,condition))
-                        (eq 'default-boundp (car-safe ,condition)))
-                    (and (eq 'quote (car-safe (nth 1 ,condition)))
-                         (nth 1 (nth 1 ,condition)))))
+  `(let* ((fbound-list (byte-compile-find-bound-condition
+                       ,condition (list 'fboundp)
+                       byte-compile-unresolved-functions))
+         (bound-list (byte-compile-find-bound-condition
+                      ,condition (list 'boundp 'default-boundp)))
          ;; Maybe add to the bound list.
          (byte-compile-bound-variables
-          (if bound
-              (cons bound byte-compile-bound-variables)
+          (if bound-list
+              (append bound-list byte-compile-bound-variables)
             byte-compile-bound-variables))
          ;; Suppress all warnings, for code not used in Emacs.
+         ;; FIXME: by the time this is executed the `featurep'
+         ;; emacs/xemacs tests have been optimized away, so this is
+         ;; not doing anything useful here, is should probably be
+         ;; moved to a different place.
+         ;; It is doing _something_. If this is commented out, then
+         ;; compiling a file which requires another file which
+         ;; defines a defsubst that uses (featurep 'xemacs) results
+         ;; in a spurious compilation warning about the xemacs code. Eg:
+         ;; (defsubst foo () (if (featurep 'xemacs) (setq foo t)))
+         ;; where foo is a free variable.
          (byte-compile-warnings
           (if (member ,condition '((featurep 'xemacs)
-                                   (not (featurep 'emacs))))
-              nil byte-compile-warnings)))
+                                   (not (featurep 'emacs))))
+              nil byte-compile-warnings))
+         )
      (unwind-protect
         (progn ,@body)
        ;; Maybe remove the function symbol from the unresolved list.
-       (if fbound
+       (dolist (fbound fbound-list)
+        (when fbound
           (setq byte-compile-unresolved-functions
                 (delq (assq fbound byte-compile-unresolved-functions)
-                      byte-compile-unresolved-functions))))))
+                      byte-compile-unresolved-functions)))))))
 
 (defun byte-compile-if (form)
   (byte-compile-form (car (cdr form)))
@@ -3799,7 +3902,7 @@ that suppresses all warnings during execution of BODY."
         (if (= 1 ncall) "" "s")
         (if (< ncall 2) "requires" "accepts only")
         "2-3")))
-    (when (memq 'free-vars byte-compile-warnings)
+    (when (byte-compile-warning-enabled-p 'free-vars)
       (push var byte-compile-bound-variables)
       (if (eq fun 'defconst)
          (push var byte-compile-const-variables)))
@@ -3891,7 +3994,7 @@ that suppresses all warnings during execution of BODY."
 (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-warning-enabled-p 'make-local))
       (byte-compile-warn
        "`make-variable-buffer-local' should be called at toplevel"))
   (byte-compile-normal-call form))
@@ -4183,7 +4286,7 @@ Must be used only with `-batch', and kills Emacs on completion.
 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
+`byte-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
@@ -4236,18 +4339,18 @@ and corresponding effects."
       (assq 'byte-code (symbol-function 'byte-compile-form))
       (let ((byte-optimize nil)                ; do it fast
            (byte-compile-warnings nil))
-       (mapcar (lambda (x)
-                 (or noninteractive (message "compiling %s..." x))
-                 (byte-compile x)
-                 (or noninteractive (message "compiling %s...done" x)))
-               '(byte-compile-normal-call
-                 byte-compile-form
-                 byte-compile-body
-                 ;; Inserted some more than necessary, to speed it up.
-                 byte-compile-top-level
-                 byte-compile-out-toplevel
-                 byte-compile-constant
-                 byte-compile-variable-ref))))
+       (mapc (lambda (x)
+               (or noninteractive (message "compiling %s..." x))
+               (byte-compile x)
+               (or noninteractive (message "compiling %s...done" x)))
+             '(byte-compile-normal-call
+               byte-compile-form
+               byte-compile-body
+               ;; Inserted some more than necessary, to speed it up.
+               byte-compile-top-level
+               byte-compile-out-toplevel
+               byte-compile-constant
+               byte-compile-variable-ref))))
   nil)
 
 (run-hooks 'bytecomp-load-hook)