Merge from emacs--rel--22
[bpt/emacs.git] / lisp / emacs-lisp / bytecomp.el
index 4b31a0e..cdc93cf 100644 (file)
 ;;                             `obsolete'  (obsolete variables and functions)
 ;;                             `noruntime' (calls to functions only defined
 ;;                                          within `eval-when-compile')
-;;                             `cl-warnings' (calls to CL functions)
+;;                             `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.
@@ -219,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)
@@ -296,6 +300,10 @@ 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.
 We bury the doc strings of functions and variables
@@ -350,14 +358,16 @@ Elements of the list may be:
   cl-functions    calls to runtime functions from the CL package (as
                  distinguished from macros and aliases).
   interactive-only
-             commands that normally shouldn't be called from Lisp code."
+             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 interactive-only))))
+                     (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)
@@ -368,7 +378,7 @@ Elements of the list may be:
                     (when (memq e '(free-vars unresolved
                                     callargs redefine
                                     obsolete noruntime
-                                    cl-functions interactive-only))
+                                    cl-functions interactive-only make-local))
                       e))
                   x)
                  x))))
@@ -470,7 +480,8 @@ 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
@@ -843,13 +854,11 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
                (when (and (consp s) (eq t (car s)))
                  (push (cdr s) old-autoloads)))))))
       (when (memq 'cl-functions byte-compile-warnings)
-       (let ((hist-new load-history)
-             (hist-nil-new current-load-list))
+       (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))
-                 old-autoloads)
+           (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)))))))))
@@ -966,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)))))
@@ -1253,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))))
@@ -1271,19 +1282,19 @@ extra args."
 ;; 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)))
+        (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)))))
+        (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.
@@ -1336,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)))))
@@ -1611,7 +1623,8 @@ This is normally set in local file variables at the end of the elisp file:
 ;;;###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")
@@ -1820,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)
@@ -1836,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
@@ -1855,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))))
@@ -1906,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
@@ -2003,7 +2015,8 @@ With argument, insert value in current buffer after the form."
          (print-level nil)
          (print-quoted t)
          (print-gensym t)
-         (print-circle t))            ; handle circular data structures
+         (print-circle              ; handle circular data structures
+          (not byte-compile-disable-print-circle)))
       (princ "\n" outbuffer)
       (prin1 form outbuffer)
       nil)))
@@ -2060,7 +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 t)        ; handle circular data structures
+              (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
@@ -2225,8 +2239,7 @@ list that represents a doc string reference.
 
 (put 'require 'byte-hunk-handler 'byte-compile-file-form-require)
 (defun byte-compile-file-form-require (form)
-  (let ((old-load-list current-load-list)
-       (args (mapcar 'eval (cdr 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))
@@ -2330,7 +2343,7 @@ 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)))))
@@ -3137,6 +3150,9 @@ That command is designed for interactive use only" fn))
 \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)
@@ -3148,6 +3164,34 @@ That command is designed for interactive use only" fn))
 (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)
@@ -3846,7 +3890,8 @@ that suppresses all warnings during execution of BODY."
 ;; 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 (eq (car-safe (car-safe (cdr-safe form))) 'quote)
+  (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))