changeset 5470:0af042a0c116

Merge with trunk.
author Mats Lidell <matsl@xemacs.org>
date Mon, 07 Feb 2011 21:22:17 +0100
parents 2a8a04f73c15 (current diff) 38e24b8be4ea (diff)
children 00e79bbbe48f
files lisp/ChangeLog lisp/bytecomp.el lisp/cl-compat.el lisp/cl-extra.el lisp/cl-macs.el lisp/cl-seq.el lisp/cl.el lisp/descr-text.el lisp/faces.el lisp/font-lock.el lisp/gtk-font-menu.el lisp/msw-font-menu.el lisp/package-get.el lisp/select.el lisp/sound.el lisp/x-font-menu.el src/ChangeLog src/abbrev.c src/device-x.c src/dired.c src/eval.c src/file-coding.c src/fileio.c src/fns.c src/fontcolor-msw.c src/intl-win32.c src/keymap.c src/lisp.h src/profile.c src/redisplay.c src/redisplay.h src/symbols.c src/unicode.c tests/ChangeLog tests/automated/lisp-tests.el
diffstat 35 files changed, 927 insertions(+), 609 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/ChangeLog	Mon Feb 07 21:22:17 2011 +0100
@@ -1,3 +1,82 @@
+2011-02-07  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* bytecomp.el:
+	* bytecomp.el (byte-compile-initial-macro-environment):
+	Shadow `block', `return-from' here, we implement them differently
+	when byte-compiling.
+
+	* bytecomp.el (byte-compile-active-blocks): New.
+	* bytecomp.el (byte-compile-block-1): New.
+	* bytecomp.el (byte-compile-return-from-1): New.
+	* bytecomp.el (return-from-1): New.
+	* bytecomp.el (block-1): New.
+	These are two aliases that exist to have their own associated
+	byte-compile functions, which functions implement `block' and
+	`return-from'.
+
+	* cl-extra.el (cl-macroexpand-all):
+	Fix a bug here when macros in the environment have been compiled.
+
+	* cl-macs.el (block):
+	* cl-macs.el (return):
+	* cl-macs.el (return-from):
+	Be more careful about lexical scope in these macros.
+
+	* cl.el:
+	* cl.el ('cl-block-wrapper): Removed.
+	* cl.el ('cl-block-throw): Removed.
+	These aren't needed in code generated by this XEmacs. They
+	shouldn't be needed in code generated by XEmacs 21.4, but if it
+	turns out the packages do need them, we can put them back.
+
+2011-01-30  Mike Sperber  <mike@xemacs.org>
+
+	* font-lock.el (font-lock-fontify-pending-extents): Don't fail if
+	`font-lock-mode' is unset, which can happen in the middle of
+	`revert-buffer'.
+
+2011-01-23  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cl-macs.el (delete):
+	* cl-macs.el (delq):
+	* cl-macs.el (remove):
+	* cl-macs.el (remq):
+	Don't use the compiler macro if these functions were given the
+	wrong number of arguments, as happens in lisp-tests.el.
+	* cl-seq.el (remove, remq): Removed.
+	I added these to subr.el, and forgot to remove them from here.
+
+2011-01-22  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* bytecomp.el (byte-compile-setq, byte-compile-set):
+	Remove kludge allowing keywords' values to be set, all the code
+	that does that is gone.
+
+	* cl-compat.el (elt-satisfies-test-p):
+	* faces.el (set-face-parent):
+	* faces.el (face-doc-string):
+	* gtk-font-menu.el:
+	* gtk-font-menu.el (gtk-reset-device-font-menus):
+	* msw-font-menu.el:
+	* msw-font-menu.el (mswindows-reset-device-font-menus):
+	* package-get.el (package-get-installedp):
+	* select.el (select-convert-from-image-data):
+	* sound.el:
+	* sound.el (load-sound-file):
+	* x-font-menu.el (x-reset-device-font-menus-core):
+	Don't quote keywords, they're self-quoting, and the
+	win from backward-compatibility is sufficiently small now that the
+	style problem overrides it.
+
+2011-01-22  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cl-macs.el (block, return-from): Require that NAME be a symbol
+	in these macros, as always documented in the #'block docstring and
+	as required by Common Lisp.
+	* descr-text.el (unidata-initialize-unihan-database):
+	Correct the use of non-symbols in #'block and #'return-from in
+	this function.
+
 2011-01-15  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* cl-extra.el (concatenate): Accept more complicated TYPEs in this
--- a/lisp/bytecomp.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/bytecomp.el	Mon Feb 07 21:22:17 2011 +0100
@@ -509,7 +509,11 @@
 		    "%s is not of type %s" form type)))
 	   (if byte-compile-delete-errors
 	       form
-	     (funcall (cdr (symbol-function 'the)) type form)))))
+	     (funcall (cdr (symbol-function 'the)) type form))))
+    (return-from .
+      ,#'(lambda (name &optional result) `(return-from-1 ',name ,result)))
+    (block .
+      ,#'(lambda (name &rest body) `(block-1 ',name ,@body))))
   "The default macro-environment passed to macroexpand by the compiler.
 Placing a macro here will cause a macro to have different semantics when
 expanded by the compiler as when expanded by the interpreter.")
@@ -3727,13 +3731,10 @@
 	    ;; Odd number of args?  Let `set' get the error.
 	    (byte-compile-form `(set ',var) for-effect)
 	  (setq val (pop args))
-	  (if (keywordp var)
-	      ;; (setq :foo ':foo) compatibility kludge
-	      (byte-compile-form `(set ',var ,val) (if args t for-effect))
-	    (byte-compile-form val)
-	    (unless (or args for-effect)
-	      (byte-compile-out 'byte-dup 0))
-	    (byte-compile-variable-ref 'byte-varset var))))))
+          (byte-compile-form val)
+          (unless (or args for-effect)
+            (byte-compile-out 'byte-dup 0))
+          (byte-compile-variable-ref 'byte-varset var)))))
   (setq for-effect nil))
 
 (defun byte-compile-set (form)
@@ -3743,11 +3744,10 @@
   (let ((symform (nth 1 form))
 	(valform (nth 2 form))
 	sym)
-    (if (and (= (length form) 3)
-	     (= (safe-length symform) 2)
+    (if (and (eql (length form) 3)
+	     (eql (safe-length symform) 2)
 	     (eq (car symform) 'quote)
-	     (symbolp (setq sym (car (cdr symform))))
-	     (not (byte-compile-constant-symbol-p sym)))
+	     (symbolp (setq sym (car (cdr symform)))))
 	(byte-compile-setq `(setq ,sym ,valform))
       (byte-compile-two-args form))))
 
@@ -4184,6 +4184,8 @@
 ;;; other tricky macro-like special-operators
 
 (byte-defop-compiler-1 catch)
+(byte-defop-compiler-1 block-1)
+(byte-defop-compiler-1 return-from-1)
 (byte-defop-compiler-1 unwind-protect)
 (byte-defop-compiler-1 condition-case)
 (byte-defop-compiler-1 save-excursion)
@@ -4198,6 +4200,39 @@
     (byte-compile-top-level (cons 'progn (cdr (cdr form))) for-effect))
   (byte-compile-out 'byte-catch 0))
 
+;; `return-from' and `block' are different from `throw' and `catch' when it
+;; comes to scope and extent. These differences are implemented for
+;; interpreted code in cl-macs.el, in compiled code in bytecomp.el. There's
+;; a certain amount of bootstrapping needed for the latter, and until this
+;; is done return-from and block behave as throw and catch in their scope
+;; and extent. This is only relevant to people working on bytecomp.el.
+
+(defalias 'return-from-1 'throw)
+(defalias 'block-1 'catch)
+
+(defvar byte-compile-active-blocks nil)
+
+(defun byte-compile-block-1 (form)
+  (let* ((name (nth 1 (nth 1 form)))
+	 (elt (list name (copy-symbol name) nil))
+	 (byte-compile-active-blocks (cons elt byte-compile-active-blocks))
+	 (body (byte-compile-top-level (cons 'progn (cddr form)))))
+    (if (nth 2 elt)
+	(byte-compile-catch `(catch ',(nth 1 elt) ,body))
+      (byte-compile-form body))))
+
+(defun byte-compile-return-from-1 (form)
+  (let* ((name (nth 1 (nth 1 form)))
+	 (assq (assq name byte-compile-active-blocks)))
+    (if assq
+	(setf (nth 2 assq) t)
+      (byte-compile-warn
+       "return-from: %S: no current lexical block with this name"
+       name))
+    (byte-compile-throw
+     `(throw ',(or (nth 1 assq) (copy-symbol name))
+             ,@(nthcdr 2 form)))))
+
 (defun byte-compile-unwind-protect (form)
   (byte-compile-push-constant
    (byte-compile-top-level-body (cdr (cdr form)) t))
--- a/lisp/cl-compat.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/cl-compat.el	Mon Feb 07 21:22:17 2011 +0100
@@ -73,9 +73,9 @@
   (assq key klist))
 
 (defun elt-satisfies-test-p (item elt klist)
-  (let ((test-not (cdr (assq ':test-not klist)))
-	(test (cdr (assq ':test klist)))
-	(key (cdr (assq ':key klist))))
+  (let ((test-not (cdr (assq :test-not klist)))
+	(test (cdr (assq :test klist)))
+	(key (cdr (assq :key klist))))
     (if key (setq elt (funcall key elt)))
     (if test-not (not (funcall test-not item elt))
       (funcall (or test 'eql) item elt))))
--- a/lisp/cl-extra.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/cl-extra.el	Mon Feb 07 21:22:17 2011 +0100
@@ -656,8 +656,11 @@
 				     '((quote --cl-rest--)))))))
 		 (list (car form) (list* 'lambda (cadadr form) body))))
 	   (let ((found (assq (cadr form) env)))
-	     ;; XEmacs: cadr/caddr operate on nil without errors
-	     (if (eq (cadr (caddr found)) 'cl-labels-args)
+	     ;; XEmacs: cadr/caddr operate on nil without errors. But the
+	     ;; macro definition may be compiled, in which case there's
+	     ;; nothing for us to do.
+	     (if (and (listp (cdr found))
+		      (eq (cadr (caddr found)) 'cl-labels-args))
 		 (cl-macroexpand-all (cadr (caddr (cadddr found))) env)
 	       form))))
 	((memq (car form) '(defun defmacro))
--- a/lisp/cl-macs.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/cl-macs.el	Mon Feb 07 21:22:17 2011 +0100
@@ -730,6 +730,7 @@
 
 
 ;;; Blocks and exits.
+(defvar cl-active-block-names nil)
 
 ;;;###autoload
 (defmacro block (name &rest body)
@@ -739,45 +740,19 @@
 in two respects:  First, the NAME is an unevaluated symbol rather than a
 quoted symbol or other form; and second, NAME is lexically rather than
 dynamically scoped:  Only references to it within BODY will work.  These
-references may appear inside macro expansions, but not inside functions
-called from BODY."
-  (if (cl-safe-expr-p (cons 'progn body)) (cons 'progn body)
-    (list 'cl-block-wrapper
-	  (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name)))
-		 body))))
-
-(defvar cl-active-block-names nil)
-
-(put 'cl-block-wrapper 'byte-compile
-     #'(lambda (cl-form)
-         (if (/= (length cl-form) 2)
-             (byte-compile-warn-wrong-args cl-form 1))
-
-         (if (fboundp 'byte-compile-form-do-effect)  ; Check for optimizing
-						     ; compiler
-             (progn
-               (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil))
-                      (cl-active-block-names (cons cl-entry
-                                                   cl-active-block-names))
-                      (cl-body (byte-compile-top-level
-                                (cons 'progn (cddr (nth 1 cl-form))))))
-                 (if (cdr cl-entry)
-                     (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form))
-                                              cl-body))
-                   (byte-compile-form cl-body))))
-           (byte-compile-form (nth 1 cl-form)))))
-
-(put 'cl-block-throw 'byte-compile
-     #'(lambda (cl-form)
-         (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names)))
-           (if cl-found (setcdr cl-found t)))
-         (byte-compile-throw (cons 'throw (cdr cl-form)))))
+references may appear inside macro expansions and in lambda expressions, but
+not inside other functions called from BODY."
+  (let ((cl-active-block-names (acons name (copy-symbol name)
+				      cl-active-block-names))
+	(body (cons 'progn body)))
+    `(catch ',(cdar cl-active-block-names)
+      ,(cl-macroexpand-all body cl-macro-environment))))
 
 ;;;###autoload
 (defmacro return (&optional result)
   "Return from the block named nil.
 This is equivalent to `(return-from nil RESULT)'."
-  (list 'return-from nil result))
+  `(return-from nil ,result))
 
 ;;;###autoload
 (defmacro return-from (name &optional result)
@@ -786,9 +761,8 @@
 returning RESULT from that form (or nil if RESULT is omitted).
 This is compatible with Common Lisp, but note that `defun' and
 `defmacro' do not create implicit blocks as they do in Common Lisp."
-  (let ((name2 (intern (format "--cl-block-%s--" name))))
-    (list 'cl-block-throw (list 'quote name2) result)))
-
+  `(throw ',(or (cdr (assq name cl-active-block-names)) (copy-symbol name))
+	  ,result))
 
 ;;; The "loop" macro.
 
@@ -3341,42 +3315,49 @@
     form))
 
 (define-compiler-macro delete (&whole form &rest args)
-  (symbol-macrolet
-      ((not-constant '#:not-constant))
-    (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
-      (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
-	       (or (symbolp cl-const-expr-val) (fixnump cl-const-expr-val)
-		   (characterp cl-const-expr-val)))
-	  (cons 'delete* (cdr form))
-	`(delete* ,@(cdr form) :test #'equal)))))
+  (if (eql 3 (length form))
+      (symbol-macrolet ((not-constant '#:not-constant))
+        (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
+          (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
+                   (or (symbolp cl-const-expr-val) (fixnump cl-const-expr-val)
+                       (characterp cl-const-expr-val)))
+              (cons 'delete* (cdr form))
+            `(delete* ,@(cdr form) :test #'equal))))
+    form))
 
 (define-compiler-macro delq (&whole form &rest args)
-  (symbol-macrolet
-      ((not-constant '#:not-constant))
-    (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
-      (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
-	       (not (cl-non-fixnum-number-p cl-const-expr-val)))
-	  (cons 'delete* (cdr form))
-	`(delete* ,@(cdr form) :test #'eq)))))
+  (if (eql 3 (length form))
+      (symbol-macrolet
+          ((not-constant '#:not-constant))
+        (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
+          (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
+                   (not (cl-non-fixnum-number-p cl-const-expr-val)))
+              (cons 'delete* (cdr form))
+            `(delete* ,@(cdr form) :test #'eq))))
+    form))
 
 (define-compiler-macro remove (&whole form &rest args)
-  (symbol-macrolet
-      ((not-constant '#:not-constant))
-    (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
-      (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
-	       (or (symbolp cl-const-expr-val) (fixnump cl-const-expr-val)
-		   (characterp cl-const-expr-val)))
-	  (cons 'remove* (cdr form))
-	`(remove* ,@(cdr form) :test #'equal)))))
+  (if (eql 3 (length form))
+      (symbol-macrolet
+          ((not-constant '#:not-constant))
+        (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
+          (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
+                   (or (symbolp cl-const-expr-val) (fixnump cl-const-expr-val)
+                       (characterp cl-const-expr-val)))
+              (cons 'remove* (cdr form))
+            `(remove* ,@(cdr form) :test #'equal))))
+    form))
 
 (define-compiler-macro remq (&whole form &rest args)
-  (symbol-macrolet
-      ((not-constant '#:not-constant))
-    (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
-      (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
-	       (not (cl-non-fixnum-number-p cl-const-expr-val)))
-	  (cons 'remove* (cdr form))
-	`(remove* ,@(cdr form) :test #'eq)))))
+  (if (eql 3 (length form))
+      (symbol-macrolet
+          ((not-constant '#:not-constant))
+        (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
+          (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
+                   (not (cl-non-fixnum-number-p cl-const-expr-val)))
+              (cons 'remove* (cdr form))
+            `(remove* ,@(cdr form) :test #'eq))))
+    form))
  
 (macrolet
     ((define-foo-if-compiler-macros (&rest alist)
--- a/lisp/cl-seq.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/cl-seq.el	Mon Feb 07 21:22:17 2011 +0100
@@ -54,26 +54,6 @@
 ;; scope (e.g. a variable called start bound in this file and one in a
 ;; user-supplied test predicate may well interfere with each other).
 
-;; XEmacs change: these two are in subr.el in GNU Emacs.
-(defun remove (cl-item cl-seq)
-  "Remove all occurrences of ITEM in SEQUENCE, testing with `equal'.
-
-This is a non-destructive function; it makes a copy of SEQUENCE if necessary
-to avoid corrupting the original SEQUENCE.
-Also see: `remove*', `delete', `delete*'
-
-arguments: (ITEM SEQUENCE)"
-  (remove* cl-item cl-seq :test #'equal))
-
-(defun remq (cl-item cl-seq)
-  "Remove all occurrences of ITEM in SEQUENCE, comparing with `eq'.
-
-This is a non-destructive function; it makes a copy of SEQUENCE to avoid
-corrupting the original LIST.  See also the more general `remove*'.
-
-arguments: (ITEM SEQUENCE)"
-  (remove* cl-item cl-seq :test #'eq))
-
 (defun remove-if (cl-predicate cl-seq &rest cl-keys)
   "Remove all items satisfying PREDICATE in SEQUENCE.
 
--- a/lisp/cl.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/cl.el	Mon Feb 07 21:22:17 2011 +0100
@@ -203,19 +203,6 @@
 
 (defalias 'cl-map-extents 'map-extents)
 
-;;; Blocks and exits.
-
-;; This used to be #'identity, but that didn't preserve multiple values in
-;; interpreted code. #'and isn't great either, there's no error on too many
-;; arguments passed to it when interpreted. Fortunately most of the places
-;; where cl-block-wrapper is called are generated from old, established
-;; macros, so too many arguments resulting from human error is unlikely; and
-;; the byte compile handler in cl-macs.el warns if more than one arg is
-;; passed to it.
-(defalias 'cl-block-wrapper 'and)
-
-(defalias 'cl-block-throw 'throw)
-
 ;;; XEmacs; multiple values are in eval.c and cl-macs.el. 
 
 ;;; We no longer support `multiple-value-apply', which was ill-conceived to
--- a/lisp/descr-text.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/descr-text.el	Mon Feb 07 21:22:17 2011 +0100
@@ -596,7 +596,7 @@
 					(concat message
 						(make-string
 						 (mod loop-count 44) ?.)))
-	  (block 'dealing-with-chars
+	  (block dealing-with-chars
 	    (when (= buffer-size (- (point-max) (point-min)))
 	      ;; If we're in the body of the file, we need to delete the
 	      ;; character info for the last character, and set offset-end
@@ -635,13 +635,13 @@
 	    (while t
 	      (when (= (point) (point-max))
 		;; We're at the end of this part of the file.
-		(return-from 'dealing-with-chars))
+		(return-from dealing-with-chars))
 
 	      (unless (re-search-forward "^\\(U\\+[0-9A-F]\\{4,6\\}\\)\t"
 					 nil t)
 		;; We're probably in the comments at the start of the
 		;; file. No need to look for character info.
-		(return-from 'dealing-with-chars))
+		(return-from dealing-with-chars))
 
 	      ;; Store where the character started. 
 	      (beginning-of-line)
--- a/lisp/faces.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/faces.el	Mon Feb 07 21:22:17 2011 +0100
@@ -416,7 +416,7 @@
                              how-to-add))
         (set-difference built-in-face-specifiers
                         '(display-table background-pixmap inherit)))
-  (set-face-background-pixmap face (vector 'inherit ':face parent)
+  (set-face-background-pixmap face (vector 'inherit :face parent)
 			      locale tag-set how-to-add)
   nil)
 
--- a/lisp/font-lock.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/font-lock.el	Mon Feb 07 21:22:17 2011 +0100
@@ -1475,51 +1475,55 @@
   (save-match-data
     (maphash
      #'(lambda (buffer dummy)
-	 ;; remove first, to avoid infinite reprocessing if error
-	 (remhash buffer font-lock-pending-buffer-table)
-	 (when (buffer-live-p buffer)
-	   (clear-range-table font-lock-range-table)
-	   (with-current-buffer buffer
-	     (save-excursion
-	       (save-restriction
-		 ;; if we don't widen, then the C code in
-		 ;; syntactically-sectionize will fail to realize that
-		 ;; we're inside a comment. #### We don't actually use
-		 ;; syntactically-sectionize any more.  Do we still
-		 ;; need the widen?
-		 (widen)
-		 (map-extents
-		  #'(lambda (ex dummy-maparg)
-		      ;; first expand the ranges to full lines,
-		      ;; because that is what will be fontified;
-		      ;; then use a range table to merge the
-		      ;; ranges. (we could also do this simply using
-		      ;; text properties.  the range table code was
-		      ;; here from a previous version of this code
-		      ;; and works just as well.)
-		      (let* ((beg (extent-start-position ex))
-			     (end (extent-end-position ex))
-			     (beg (progn (goto-char beg)
-					 (beginning-of-line)
-					 (point)))
-			     (end (progn (goto-char end)
-					 (forward-line 1)
-					 (point))))
-			(put-range-table beg end t
-					 font-lock-range-table)))
-		  nil nil nil nil nil 'font-lock-pending t)
-		 ;; clear all pending extents first in case of error below.
-		 (put-text-property (point-min) (point-max)
-				    'font-lock-pending nil)
-		 (map-range-table
-		  #'(lambda (beg end val)
+	 (catch 'exit
+	   ;; font-lock-mode may be temporarily unset during `revert-buffer'
+	   (if (not font-lock-mode)
+	       (throw 'exit nil))
+	   ;; remove first, to avoid infinite reprocessing if error
+	   (remhash buffer font-lock-pending-buffer-table)
+	   (when (buffer-live-p buffer)
+	     (clear-range-table font-lock-range-table)
+	     (with-current-buffer buffer
+	       (save-excursion
+		 (save-restriction
+		   ;; if we don't widen, then the C code in
+		   ;; syntactically-sectionize will fail to realize that
+		   ;; we're inside a comment. #### We don't actually use
+		   ;; syntactically-sectionize any more.  Do we still
+		   ;; need the widen?
+		   (widen)
+		   (map-extents
+		    #'(lambda (ex dummy-maparg)
+			;; first expand the ranges to full lines,
+			;; because that is what will be fontified;
+			;; then use a range table to merge the
+			;; ranges. (we could also do this simply using
+			;; text properties.  the range table code was
+			;; here from a previous version of this code
+			;; and works just as well.)
+			(let* ((beg (extent-start-position ex))
+			       (end (extent-end-position ex))
+			       (beg (progn (goto-char beg)
+					   (beginning-of-line)
+					   (point)))
+			       (end (progn (goto-char end)
+					   (forward-line 1)
+					   (point))))
+			  (put-range-table beg end t
+					   font-lock-range-table)))
+		    nil nil nil nil nil 'font-lock-pending t)
+		   ;; clear all pending extents first in case of error below.
+		   (put-text-property (point-min) (point-max)
+				      'font-lock-pending nil)
+		   (map-range-table
+		    #'(lambda (beg end val)
 			;; This creates some unnecessary progress gauges.
 ;;			(if (and (= beg (point-min))
 ;;				 (= end (point-max)))
 ;;			    (font-lock-fontify-buffer)
 ;;			  (font-lock-fontify-region beg end)))
-		      (font-lock-fontify-region beg end))
-		  font-lock-range-table))))))
+			(font-lock-fontify-region beg end))
+		    font-lock-range-table)))))))
      font-lock-pending-buffer-table)))
 
 ;; Syntactic fontification functions.
--- a/lisp/gtk-font-menu.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/gtk-font-menu.el	Mon Feb 07 21:22:17 2011 +0100
@@ -166,19 +166,19 @@
       (mapcar (lambda (x)
 		(vector x
 			(list 'font-menu-set-font x nil nil)
-			':style 'radio ':active nil ':selected nil))
+			:style 'radio :active nil :selected nil))
 	      families)
       (mapcar (lambda (x)
 		(vector (if (/= 0 (% x 10))
 			    (number-to-string (/ x 10.0))
 			  (number-to-string (/ x 10)))
 			(list 'font-menu-set-font nil nil x)
-			':style 'radio ':active nil ':selected nil))
+			:style 'radio :active nil :selected nil))
 	      sizes)
       (mapcar (lambda (x)
 		(vector x
 			(list 'font-menu-set-font nil x nil)
-			':style 'radio ':active nil ':selected nil))
+			:style 'radio :active nil :selected nil))
 	      weights)))
     (cdr dev-cache)))
 
--- a/lisp/msw-font-menu.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/msw-font-menu.el	Mon Feb 07 21:22:17 2011 +0100
@@ -138,17 +138,17 @@
 	(mapcar (lambda (x)
 		  (vector x
 			  (list 'font-menu-set-font x nil nil)
-			  ':style 'radio ':active nil ':selected nil))
+			  :style 'radio :active nil :selected nil))
 		families)
 	(mapcar (lambda (x)
 		  (vector (int-to-string x)
 			  (list 'font-menu-set-font nil nil x)
-			  ':style 'radio ':active nil ':selected nil))
+			  :style 'radio :active nil :selected nil))
 		sizes)
 	(mapcar (lambda (x)
 		  (vector x
 			  (list 'font-menu-set-font nil x nil)
-			  ':style 'radio ':active nil ':selected nil))
+			  :style 'radio :active nil :selected nil))
 		weights)))
       (cdr dev-cache)))
 
--- a/lisp/package-get.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/package-get.el	Mon Feb 07 21:22:17 2011 +0100
@@ -1238,7 +1238,7 @@
   ;; Use packages-package-list which contains name and version
   (equal (plist-get
 	  (package-get-info-find-package packages-package-list
-					 package) ':version)
+					 package) :version)
 	 (if (floatp version)
 	     version
 	   (string-to-number version))))
--- a/lisp/select.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/select.el	Mon Feb 07 21:22:17 2011 +0100
@@ -765,7 +765,7 @@
 corresponding to that data as an end-glyph extent property of that space. "
   (let* ((str (make-string 1 ?\ ))
 	 (extent (make-extent 0 1 str))
-	 (glyph (make-glyph (vector image-type ':data value))))
+	 (glyph (make-glyph (vector image-type :data value))))
     (when glyph
       (set-extent-property extent 'invisible t)
       (set-extent-property extent 'start-open t)
--- a/lisp/sound.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/sound.el	Mon Feb 07 21:22:17 2011 +0100
@@ -179,8 +179,8 @@
     (setq sound-alist (cons
 		       (nconc (list sound-name)
 			      (if (and volume (not (eq 0 volume)))
-				  (list ':volume volume))
-			      (list ':sound data))
+				  (list :volume volume))
+			      (list :sound data))
 		       sound-alist)))
   sound-name)
 
--- a/lisp/x-font-menu.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/lisp/x-font-menu.el	Mon Feb 07 21:22:17 2011 +0100
@@ -251,21 +251,21 @@
      (vector
       cache
       (mapcar (lambda (x)
-		(vector x
+                (vector x
 			(list 'font-menu-set-font x nil nil)
-			':style 'radio ':active nil ':selected nil))
+			:style 'radio :active nil :selected nil))
 	      families)
       (mapcar (lambda (x)
 		(vector (if (/= 0 (% x 10))
 			    (number-to-string (/ x 10.0))
 			  (number-to-string (/ x 10)))
 			(list 'font-menu-set-font nil nil x)
-			':style 'radio ':active nil ':selected nil))
+			:style 'radio :active nil :selected nil))
 	      sizes)
       (mapcar (lambda (x)
 		(vector x
 			(list 'font-menu-set-font nil x nil)
-			':style 'radio ':active nil ':selected nil))
+			:style 'radio :active nil :selected nil))
 	      weights)))
     (cdr dev-cache)))
 
--- a/src/ChangeLog	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/ChangeLog	Mon Feb 07 21:22:17 2011 +0100
@@ -1,3 +1,74 @@
+2011-02-07  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* keymap.c (describe_map_sort_predicate): Correct the order of
+	arguments to map_keymap_sort_predicate() here. Thanks again, Mats.
+
+2011-02-06  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* symbols.c (Fapropos_internal):
+	Supply check_string_lessp_nokey explicitly as the CHECK_MERGE
+	argument to list_sort(), NULL no longer works. Thank you Mats
+	Lidell in IRC!
+
+2011-02-05  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* fns.c:
+	* fns.c (check_lss_key, check_lss_key_car): New.
+	* fns.c (check_string_lessp_key check_string_lessp_key_car): New.
+	* fns.c (get_merge_predicate): New.
+	* fns.c (list_merge):
+	* fns.c (array_merge):
+	* fns.c (list_array_merge_into_list):
+	* fns.c (list_list_merge_into_array):
+	* fns.c (list_array_merge_into_array):
+	* fns.c (Fmerge):
+	* fns.c (list_sort):
+	* fns.c (array_sort):
+	* fns.c (FsortX):
+	* fns.c (syms_of_fns):
+	* lisp.h:
+	Move #'sort, #'merge to using the same test approach as is used in
+	the functions that take TEST, TEST-NOT and KEY arguments.  This
+	allows us to avoid the Ffuncall() overhead when the most common
+	PREDICATE arguments are supplied, in particular #'< and
+	#'string-lessp.
+
+	* fontcolor-msw.c (sort_font_list_function):
+	* fontcolor-msw.c (mswindows_enumerate_fonts):
+	* dired.c:
+	* dired.c (Fdirectory_files):
+	* fileio.c:
+	* fileio.c (build_annotations):
+	* fileio.c (syms_of_fileio):
+	* keymap.c:
+	* keymap.c (keymap_submaps):
+	* keymap.c (map_keymap_sort_predicate):
+	* keymap.c (describe_map_sort_predicate):
+	* keymap.c (describe_map):
+	Change the various C predicates passed to list_sort () and
+	list_merge () to fit the new calling convention, returning
+	non-zero if the first argument is less than the second, zero
+	otherwise.
+
+2011-01-30  Michael Sperber  <mike@xemacs.org>
+
+	* redisplay.h: 
+	* redisplay.c: 
+	(redisplay_cancel_ritual_suicide): 
+	* eval.c (throw_or_bomb_out_unsafe): 
+	* device-x.c (x_IO_error_handler): Don't commit suicide when an X
+	device dies.
+
+2011-01-23  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* file-coding.c (complex_vars_of_file_coding):
+	* intl-win32.c (complex_vars_of_intl_win32):
+	* profile.c (Fget_profiling_info):
+	* unicode.c (complex_vars_of_unicode):
+	Replace various awkward calls to nconc2 () with list6 () with
+	analogous calls to Ben's relatively-recently introduced listu (),
+	constructing a list from an arbitrary number of C arguments.
+
 2011-01-18  Mike Sperber  <mike@xemacs.org>
 
 	* s/freebsd.h: Zap. Not really needed anymore, and it has unclear
--- a/src/abbrev.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/abbrev.c	Mon Feb 07 21:22:17 2011 +0100
@@ -522,7 +522,7 @@
   map_obarray (table, record_symbol, &symbols);
   /* map_obarray (table, record_symbol, &closure); */
   symbols = XCDR (symbols);
-  symbols = list_sort (symbols, NULL, Qstring_lessp, Qidentity);
+  symbols = list_sort (symbols, check_string_lessp_nokey, Qnil, Qnil);
 
   if (!NILP (readable))
     {
--- a/src/device-x.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/device-x.c	Mon Feb 07 21:22:17 2011 +0100
@@ -1253,7 +1253,8 @@
       DEVICE_X_BEING_DELETED (d) = 1;
     }
 
-  throw_or_bomb_out (Qtop_level, Qnil, 0, Qnil, Qnil);
+  redisplay_cancel_ritual_suicide();
+  throw_or_bomb_out_unsafe (Qtop_level, Qnil, 0, Qnil, Qnil);
 
   RETURN_NOT_REACHED (0);
 }
--- a/src/dired.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/dired.c	Mon Feb 07 21:22:17 2011 +0100
@@ -179,7 +179,7 @@
   unbind_to (speccount);	/* This will close the dir */
 
   if (NILP (nosort))
-    list = list_sort (Fnreverse (list), NULL, Qstring_lessp, Qidentity);
+    list = list_sort (Fnreverse (list), check_string_lessp_nokey, Qnil, Qnil);
 
   RETURN_UNGCPRO (list);
 }
--- a/src/eval.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/eval.c	Mon Feb 07 21:22:17 2011 +0100
@@ -1800,22 +1800,13 @@
   LONGJMP (c->jmp, 1);
 }
 
-DECLARE_DOESNT_RETURN (throw_or_bomb_out (Lisp_Object, Lisp_Object, int,
+DECLARE_DOESNT_RETURN (throw_or_bomb_out_unsafe (Lisp_Object, Lisp_Object, int,
 					  Lisp_Object, Lisp_Object));
 
 DOESNT_RETURN
-throw_or_bomb_out (Lisp_Object tag, Lisp_Object val, int bomb_out_p,
-		   Lisp_Object sig, Lisp_Object data)
-{
-#ifdef DEFEND_AGAINST_THROW_RECURSION
-  /* die if we recurse more than is reasonable */
-  assert (++throw_level <= 20);
-#endif
-
-#ifdef ERROR_CHECK_TRAPPING_PROBLEMS
-  check_proper_critical_section_nonlocal_exit_protection ();
-#endif
-
+throw_or_bomb_out_unsafe (Lisp_Object tag, Lisp_Object val, int bomb_out_p,
+			  Lisp_Object sig, Lisp_Object data)
+{
   /* If bomb_out_p is t, this is being called from Fsignal as a
      "last resort" when there is no handler for this error and
       the debugger couldn't be invoked, so we are throwing to
@@ -1855,6 +1846,24 @@
         call1 (Qreally_early_error_handler, Fcons (sig, data));
     }
 }
+  
+DECLARE_DOESNT_RETURN (throw_or_bomb_out (Lisp_Object, Lisp_Object, int,
+					  Lisp_Object, Lisp_Object));
+
+DOESNT_RETURN
+throw_or_bomb_out (Lisp_Object tag, Lisp_Object val, int bomb_out_p,
+		   Lisp_Object sig, Lisp_Object data)
+{
+#ifdef DEFEND_AGAINST_THROW_RECURSION
+  /* die if we recurse more than is reasonable */
+  assert (++throw_level <= 20);
+#endif
+
+#ifdef ERROR_CHECK_TRAPPING_PROBLEMS
+  check_proper_critical_section_nonlocal_exit_protection ();
+#endif
+  throw_or_bomb_out_unsafe (tag, val, bomb_out_p, sig, data);
+}
 
 /* See above, where CATCHLIST is defined, for a description of how
    Fthrow() works.
--- a/src/file-coding.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/file-coding.c	Mon Feb 07 21:22:17 2011 +0100
@@ -4815,142 +4815,143 @@
   Fmake_coding_system_internal
     (Qconvert_eol_cr, Qconvert_eol,
      build_defer_string ("Convert CR to LF"),
-     nconc2 (list6 (Qdocumentation,
-		    build_defer_string (
+     listu (Qdocumentation,
+            build_defer_string (
 "Converts CR (used to mark the end of a line on Macintosh systems) to LF\n"
 "(used internally and under Unix to mark the end of a line)."),
-		    Qmnemonic, build_ascstring ("CR->LF"),
-		    Qsubtype, Qcr),
-	     /* VERY IMPORTANT!  Tell make-coding-system not to generate
-		subsidiaries -- it needs the coding systems we're creating
+            Qmnemonic, build_ascstring ("CR->LF"),
+            Qsubtype, Qcr,
+            /* VERY IMPORTANT!  Tell make-coding-system not to generate
+               subsidiaries -- it needs the coding systems we're creating
 		to do so! */
-	     list4 (Qeol_type, Qlf,
-                    Qsafe_charsets, Qt)));
-
+            Qeol_type, Qlf,
+            Qsafe_charsets, Qt,
+            Qunbound));
   Fmake_coding_system_internal
     (Qconvert_eol_lf, Qconvert_eol,
      build_defer_string ("Convert LF to LF (do nothing)"),
-     nconc2 (list6 (Qdocumentation,
-		    build_defer_string (
-"Do nothing."),
-		    Qmnemonic, build_ascstring ("LF->LF"),
-		    Qsubtype, Qlf),
-	     /* VERY IMPORTANT!  Tell make-coding-system not to generate
+     listu (Qdocumentation,
+            build_defer_string ("Do nothing."),
+            Qmnemonic, build_ascstring ("LF->LF"),
+            Qsubtype, Qlf,
+            /* VERY IMPORTANT!  Tell make-coding-system not to generate
 		subsidiaries -- it needs the coding systems we're creating
 		to do so! */
-	     list4 (Qeol_type, Qlf,
-                    Qsafe_charsets, Qt)));
+	    Qeol_type, Qlf,
+            Qsafe_charsets, Qt,
+            Qunbound));
 
   Fmake_coding_system_internal
     (Qconvert_eol_crlf, Qconvert_eol,
      build_defer_string ("Convert CRLF to LF"),
-     nconc2 (list6 (Qdocumentation,
-		    build_defer_string (
+     listu (Qdocumentation,
+            build_defer_string (
 "Converts CR+LF (used to mark the end of a line on Macintosh systems) to LF\n"
 "(used internally and under Unix to mark the end of a line)."),
-		    Qmnemonic, build_ascstring ("CRLF->LF"),
-		    Qsubtype, Qcrlf),
-
-	     /* VERY IMPORTANT!  Tell make-coding-system not to generate
-		subsidiaries -- it needs the coding systems we're creating
-		to do so! */
-	     list4 (Qeol_type, Qlf,
-                    Qsafe_charsets, Qt)));
+            Qmnemonic, build_ascstring ("CRLF->LF"),
+            Qsubtype, Qcrlf,
+            /* VERY IMPORTANT!  Tell make-coding-system not to generate
+               subsidiaries -- it needs the coding systems we're creating
+               to do so! */
+            Qeol_type, Qlf,
+            Qsafe_charsets, Qt,
+            Qunbound));
 
   Fmake_coding_system_internal
     (Qconvert_eol_autodetect, Qconvert_eol,
      build_defer_string ("Autodetect EOL type"),
-     nconc2 (list6 (Qdocumentation,
-		    build_defer_string (
-"Autodetect the end-of-line type."),
-		    Qmnemonic, build_ascstring ("Auto-EOL"),
-		    Qsubtype, Qnil),
-	     /* VERY IMPORTANT!  Tell make-coding-system not to generate
-		subsidiaries -- it needs the coding systems we're creating
-		to do so! */
-	     list4 (Qeol_type, Qlf,
-                    Qsafe_charsets, Qt)));
+     listu (Qdocumentation,
+            build_defer_string ("Autodetect the end-of-line type."),
+            Qmnemonic, build_ascstring ("Auto-EOL"),
+            Qsubtype, Qnil,
+            /* VERY IMPORTANT!  Tell make-coding-system not to generate
+               subsidiaries -- it needs the coding systems we're creating
+               to do so! */
+            Qeol_type, Qlf,
+            Qsafe_charsets, Qt,
+            Qunbound));
 
   Fmake_coding_system_internal
     (Qundecided, Qundecided,
      build_defer_string ("Undecided (auto-detect)"),
-     nconc2 (list4 (Qdocumentation,
-		    build_defer_string
-		    ("Automatically detects the correct encoding."),
-		    Qmnemonic, build_ascstring ("Auto")),
-	     list6 (Qdo_eol, Qt, Qdo_coding, Qt,
-		    /* We do EOL detection ourselves so we don't need to be
-		       wrapped in an EOL detector. (It doesn't actually hurt,
-		       though, I don't think.) */
-		    Qeol_type, Qlf)));
+     listu (Qdocumentation,
+            build_defer_string ("Automatically detects the correct encoding."),
+            Qmnemonic, build_ascstring ("Auto"),
+            Qdo_eol, Qt, Qdo_coding, Qt,
+            /* We do EOL detection ourselves so we don't need to be
+               wrapped in an EOL detector. (It doesn't actually hurt,
+               though, I don't think.) */
+            Qeol_type, Qlf,
+            Qunbound));
 
   Fmake_coding_system_internal
     (intern ("undecided-dos"), Qundecided,
      build_defer_string ("Undecided (auto-detect) (CRLF)"),
-     nconc2 (list4 (Qdocumentation,
-		    build_defer_string
-		    ("Automatically detects the correct encoding; EOL type of CRLF forced."),
-		    Qmnemonic, build_ascstring ("Auto")),
-	     list4 (Qdo_coding, Qt,
-		    Qeol_type, Qcrlf)));
+     listu (Qdocumentation,
+            build_defer_string
+            ("Automatically detects the correct encoding; EOL type of CRLF forced."),
+            Qmnemonic, build_ascstring ("Auto"),
+            Qdo_coding, Qt,
+            Qeol_type, Qcrlf,
+            Qunbound));
 
   Fmake_coding_system_internal
     (intern ("undecided-unix"), Qundecided,
      build_defer_string ("Undecided (auto-detect) (LF)"),
-     nconc2 (list4 (Qdocumentation,
-		    build_defer_string
-		    ("Automatically detects the correct encoding; EOL type of LF forced."),
-		    Qmnemonic, build_ascstring ("Auto")),
-	     list4 (Qdo_coding, Qt,
-		    Qeol_type, Qlf)));
+     listu (Qdocumentation,
+            build_defer_string
+            ("Automatically detects the correct encoding; EOL type of LF forced."),
+            Qmnemonic, build_ascstring ("Auto"),
+            Qdo_coding, Qt,
+            Qeol_type, Qlf,
+            Qunbound));;
 
   Fmake_coding_system_internal
     (intern ("undecided-mac"), Qundecided,
      build_defer_string ("Undecided (auto-detect) (CR)"),
-     nconc2 (list4 (Qdocumentation,
-		    build_defer_string
-		    ("Automatically detects the correct encoding; EOL type of CR forced."),
-		    Qmnemonic, build_ascstring ("Auto")),
-	     list4 (Qdo_coding, Qt,
-		    Qeol_type, Qcr)));
+     listu (Qdocumentation,
+            build_defer_string
+            ("Automatically detects the correct encoding; EOL type of CR forced."),
+            Qmnemonic, build_ascstring ("Auto"),
+            Qdo_coding, Qt,
+            Qeol_type, Qcr,
+            Qunbound));
 
   /* Need to create this here or we're really screwed. */
   Fmake_coding_system_internal
     (Qraw_text, Qno_conversion,
      build_defer_string ("Raw Text"),
-     nconc2 (list4 (Qdocumentation,
-                    build_defer_string ("Raw text converts only line-break "
-                                      "codes, and acts otherwise like "
-                                      "`binary'."),
-                    Qmnemonic, build_ascstring ("Raw")),
+     listu (Qdocumentation,
+            build_defer_string ("Raw text converts only line-break "
+                                "codes, and acts otherwise like "
+                                "`binary'."),
+            Qmnemonic, build_ascstring ("Raw"),
 #ifdef MULE
-             list2 (Qsafe_charsets, list3 (Vcharset_ascii, Vcharset_control_1,
-                                           Vcharset_latin_iso8859_1))));
-
-#else
-             Qnil));
+            Qsafe_charsets, list3 (Vcharset_ascii, Vcharset_control_1,
+                                   Vcharset_latin_iso8859_1),
+
 #endif
+            Qunbound));
+
 
   Fmake_coding_system_internal
     (Qbinary, Qno_conversion,
      build_defer_string ("Binary"),
-     nconc2 (list6 (Qdocumentation,
-                    build_defer_string (
+     listu (Qdocumentation,
+            build_defer_string (
 "This coding system is as close as it comes to doing no conversion.\n"
 "On input, each byte is converted directly into the character\n"
 "with the corresponding code -- i.e. from the `ascii', `control-1',\n"
 "or `latin-1' character sets.  On output, these characters are\n"
 "converted back to the corresponding bytes, and other characters\n"
 "are converted to the default character, i.e. `~'."),
-                    Qeol_type, Qlf,
-                    Qmnemonic, build_ascstring ("Binary")),
+            Qeol_type, Qlf,
+            Qmnemonic, build_ascstring ("Binary"),
 #ifdef MULE
-             list2 (Qsafe_charsets, list3 (Vcharset_ascii, Vcharset_control_1,
-                                           Vcharset_latin_iso8859_1))));
-
-#else
-             Qnil));
+            Qsafe_charsets, list3 (Vcharset_ascii, Vcharset_control_1,
+                                   Vcharset_latin_iso8859_1),
 #endif
+            Qunbound));
 
   /* Formerly aliased to raw-text!  Completely bogus and not even the same
      as FSF Emacs. */
--- a/src/fileio.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/fileio.c	Mon Feb 07 21:22:17 2011 +0100
@@ -130,8 +130,6 @@
 Lisp_Object Qauto_save_error;
 Lisp_Object Qauto_saving;
 
-Lisp_Object Qcar_less_than_car;
-
 Lisp_Object Qcompute_buffer_file_truename;
 
 Lisp_Object QSin_expand_file_name;
@@ -3675,7 +3673,8 @@
 	  annotations = Qnil;
 	}
       Flength (res);     /* Check basic validity of return value */
-      annotations = list_merge (annotations, res, NULL, Qlss, Qcar);
+      annotations = list_merge (annotations, res, check_lss_key_car, Qnil,
+				Qnil);
       p = Fcdr (p);
     }
 
@@ -3706,7 +3705,8 @@
 	  annotations = Qnil;
 	}
       Flength (res);
-      annotations = list_merge (annotations, res, NULL, Qlss, Qcar);
+      annotations = list_merge (annotations, res, check_lss_key_car, Qnil,
+				Qnil);
       p = Fcdr (p);
     }
 
@@ -4379,7 +4379,6 @@
   DEFSYMBOL (Qwrite_region);
   DEFSYMBOL (Qverify_visited_file_modtime);
   DEFSYMBOL (Qset_visited_file_modtime);
-  DEFSYMBOL (Qcar_less_than_car); /* Vomitous! */
   DEFSYMBOL (Qexcl);
 
   DEFSYMBOL (Qauto_save_hook);
--- a/src/fns.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/fns.c	Mon Feb 07 21:22:17 2011 +0100
@@ -61,7 +61,7 @@
 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch;
 
 Lisp_Object Qintersection, Qset_difference, Qnset_difference;
-Lisp_Object Qnunion, Qnintersection, Qsubsetp;
+Lisp_Object Qnunion, Qnintersection, Qsubsetp, Qcar_less_than_car;
 
 Lisp_Object Qbase64_conversion_error;
 
@@ -208,9 +208,6 @@
 /* Various test functions for #'member*, #'assoc* and the other functions
    that take both TEST and KEY arguments.  */
 
-typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key,
-				      Lisp_Object item, Lisp_Object elt);
-
 static Boolint
 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
 		Lisp_Object item, Lisp_Object elt)
@@ -437,7 +434,84 @@
 
   return !NILP (elt1);
 }
-
+
+static Boolint
+check_lss_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
+		 Lisp_Object elt1, Lisp_Object elt2)
+{
+  return bytecode_arithcompare (elt1, elt2) < 0;
+}
+
+static Boolint
+check_lss_key (Lisp_Object UNUSED (test), Lisp_Object key,
+	       Lisp_Object elt1, Lisp_Object elt2)
+{
+  Lisp_Object args[] = { key, elt1, elt2 };
+  struct gcpro gcpro1;
+
+  GCPRO1 (args[0]);
+  gcpro1.nvars = countof (args);
+  args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
+  args[1] = key;
+  args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
+  UNGCPRO;
+
+  return bytecode_arithcompare (args[0], args[1]) < 0;
+}
+
+Boolint
+check_lss_key_car (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
+		   Lisp_Object elt1, Lisp_Object elt2)
+{
+  struct gcpro gcpro1, gcpro2;
+
+  GCPRO2 (elt1, elt2);
+  elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
+  elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
+  UNGCPRO;
+
+  return bytecode_arithcompare (elt1, elt2) < 0;
+}
+
+Boolint
+check_string_lessp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
+			  Lisp_Object elt1, Lisp_Object elt2)
+{
+  return !NILP (Fstring_lessp (elt1, elt2));
+}
+
+static Boolint
+check_string_lessp_key (Lisp_Object UNUSED (test), Lisp_Object key,
+			Lisp_Object elt1, Lisp_Object elt2)
+{
+  Lisp_Object args[] = { key, elt1, elt2 };
+  struct gcpro gcpro1;
+
+  GCPRO1 (args[0]);
+  gcpro1.nvars = countof (args);
+  args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
+  args[1] = key;
+  args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
+  UNGCPRO;
+
+  return !NILP (Fstring_lessp (args[0], args[1]));
+}
+
+static Boolint
+check_string_lessp_key_car (Lisp_Object UNUSED (test),
+			    Lisp_Object UNUSED (key),
+			    Lisp_Object elt1, Lisp_Object elt2)
+{
+  struct gcpro gcpro1, gcpro2;
+
+  GCPRO2 (elt1, elt2);
+  elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
+  elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
+  UNGCPRO;
+
+  return !NILP (Fstring_lessp (elt1, elt2));
+}
+
 static check_test_func_t
 get_check_match_function_1 (Lisp_Object item,
 			    Lisp_Object *test_inout, Lisp_Object test_not,
@@ -644,6 +718,72 @@
 				     test_not_unboundp_out, test_func_out);
 }
 
+/* Given PREDICATE and KEY, return a C function pointer appropriate for use
+   in deciding whether one given elements of a sequence is less than
+   another. */
+
+static check_test_func_t
+get_merge_predicate (Lisp_Object predicate, Lisp_Object key)
+{
+  predicate = indirect_function (predicate, 1);
+
+  if (NILP (key))
+    {
+      key = Qidentity;
+    }
+  else
+    {
+      key = indirect_function (key, 1);
+      if (EQ (key, XSYMBOL_FUNCTION (Qidentity)))
+	{
+	  key = Qidentity;
+	}
+    }
+
+  if (EQ (key, Qidentity) && EQ (predicate,
+				 XSYMBOL_FUNCTION (Qcar_less_than_car)))
+    {
+      key = XSYMBOL_FUNCTION (Qcar);
+      predicate = XSYMBOL_FUNCTION (Qlss);
+    }
+
+  if (EQ (predicate, XSYMBOL_FUNCTION (Qlss)))
+    {
+      if (EQ (key, Qidentity))
+	{
+	  return check_lss_nokey;
+	}
+
+      if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
+	{
+	  return check_lss_key_car;
+	}
+
+      return check_lss_key;
+    }
+
+  if (EQ (predicate, XSYMBOL_FUNCTION (Qstring_lessp)))
+    {
+      if (EQ (key, Qidentity))
+	{
+	  return check_string_lessp_nokey;
+	}
+
+      if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
+	{
+	  return check_string_lessp_key_car;
+	}
+
+      return check_string_lessp_key;
+    }
+
+  if (EQ (key, Qidentity))
+    {
+      return check_other_nokey;
+    }
+
+  return check_match_other_key;
+}
 
 DEFUN ("identity", Fidentity, 1, 1, 0, /*
 Return the argument unchanged.
@@ -4692,58 +4832,10 @@
   return result;
 }
 
-static Lisp_Object
-c_merge_predicate_key (Lisp_Object obj1, Lisp_Object obj2,
-                       Lisp_Object pred, Lisp_Object key_func)
-{
-  struct gcpro gcpro1;
-  Lisp_Object args[3];
-
-  /* We could use call2() and call3() here, but we're called O(nlogn) times
-     for a sequence of length n, it make some sense to inline them. */
-  args[0] = key_func;
-  args[1] = obj1;
-  args[2] = Qnil;
-
-  GCPRO1 (args[0]);
-  gcpro1.nvars = countof (args);
-
-  obj1 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
-
-  args[1] = obj2;
-  obj2 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
-
-  args[0] = pred;
-  args[1] = obj1;
-  args[2] = obj2;
-
-  RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)));
-}
-
-static Lisp_Object
-c_merge_predicate_nokey (Lisp_Object obj1, Lisp_Object obj2,
-                         Lisp_Object pred, Lisp_Object UNUSED (key_func))
-{
-  struct gcpro gcpro1;
-  Lisp_Object args[3];
-
-  /* This is (almost) the implementation of call2, it makes some sense to
-     inline it here. */
-  args[0] = pred;
-  args[1] = obj1;
-  args[2] = obj2;
-
-  GCPRO1 (args[0]);
-  gcpro1.nvars = countof (args);
-
-  RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)));
-}
-
 Lisp_Object
 list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
-            Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object,
-                                        Lisp_Object, Lisp_Object),
-            Lisp_Object predicate, Lisp_Object key_func)
+	    check_test_func_t check_merge,
+	    Lisp_Object predicate, Lisp_Object key)
 {
   Lisp_Object value;
   Lisp_Object tail;
@@ -4760,15 +4852,8 @@
   tortoises[0] = org_l1;
   tortoises[1] = org_l2; 
 
-  if (NULL == c_predicate)
-    {
-      c_predicate = EQ (key_func, Qidentity) ?
-        c_merge_predicate_nokey : c_merge_predicate_key;
-    }
-
-  /* It is sufficient to protect org_l1 and org_l2.
-     When l1 and l2 are updated, we copy the new values
-     back into the org_ vars.  */
+  /* It is sufficient to protect org_l1 and org_l2.  When l1 and l2 are
+     updated, we copy the new values back into the org_ vars.  */
 
   GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]);
   gcpro5.nvars = 2;
@@ -4792,7 +4877,7 @@
 	  return value;
 	}
 
-      if (NILP (c_predicate (Fcar (l2), Fcar (l1), predicate, key_func)))
+      if (check_merge (predicate, key, Fcar (l2), Fcar (l1)) == 0)
 	{
 	  tem = l1;
 	  l1 = Fcdr (l1);
@@ -4854,9 +4939,8 @@
 array_merge (Lisp_Object *dest, Elemcount dest_len,
              Lisp_Object *front, Elemcount front_len,
              Lisp_Object *back, Elemcount back_len,
-             Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object,
-                                         Lisp_Object, Lisp_Object),
-             Lisp_Object predicate, Lisp_Object key_func)
+	     check_test_func_t check_merge,
+             Lisp_Object predicate, Lisp_Object key)
 {
   Elemcount ii, fronting, backing;
   Lisp_Object *front_staging = front;
@@ -4918,8 +5002,8 @@
           return;
         }
 
-      if (NILP (c_predicate (back_staging[backing], front_staging[fronting],
-                             predicate, key_func)))
+      if (check_merge (predicate, key, back_staging[backing],
+		       front_staging[fronting]) == 0)
         {
           dest[ii] = front_staging[fronting];
           ++fronting;
@@ -4937,11 +5021,8 @@
 static Lisp_Object
 list_array_merge_into_list (Lisp_Object list,
                             Lisp_Object *array, Elemcount array_len,
-                            Lisp_Object (*c_predicate) (Lisp_Object,
-                                                        Lisp_Object,
-                                                        Lisp_Object,
-                                                        Lisp_Object),
-                            Lisp_Object predicate, Lisp_Object key_func,
+			    check_test_func_t check_merge,
+                            Lisp_Object predicate, Lisp_Object key,
                             Boolint reverse_order)
 {
   Lisp_Object tail = Qnil, value = Qnil, tortoise = list;
@@ -4980,10 +5061,8 @@
 
 
       if (reverse_order ?
-          !NILP (c_predicate (Fcar (list), array [array_index], predicate,
-                              key_func)) :
-          NILP (c_predicate (array [array_index], Fcar (list), predicate,
-                             key_func)))
+	  check_merge (predicate, key, Fcar (list), array [array_index])
+	  : !check_merge (predicate, key, array [array_index], Fcar (list)))
         {
           if (NILP (tail))
             {
@@ -5029,11 +5108,8 @@
 static void
 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len,
                             Lisp_Object list_one, Lisp_Object list_two,
-                            Lisp_Object (*c_predicate) (Lisp_Object,
-                                                        Lisp_Object,
-                                                        Lisp_Object,
-                                                        Lisp_Object),
-                            Lisp_Object predicate, Lisp_Object key_func)
+			    check_test_func_t check_merge,
+                            Lisp_Object predicate, Lisp_Object key)
 {
   Elemcount output_index = 0;
 
@@ -5059,8 +5135,8 @@
           return;
         }
 
-      if (NILP (c_predicate (Fcar (list_two), Fcar (list_one), predicate,
-                             key_func)))
+      if (check_merge (predicate, key, Fcar (list_two), Fcar (list_one))
+	  == 0)
         {
           output [output_index] = XCAR (list_one);
           list_one = XCDR (list_one);
@@ -5081,11 +5157,8 @@
 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len,
                              Lisp_Object list,
                              Lisp_Object *array, Elemcount array_len,
-                             Lisp_Object (*c_predicate) (Lisp_Object,
-                                                         Lisp_Object,
-                                                         Lisp_Object,
-                                                         Lisp_Object),
-                             Lisp_Object predicate, Lisp_Object key_func,
+			     check_test_func_t check_merge,
+                             Lisp_Object predicate, Lisp_Object key,
                              Boolint reverse_order)
 {
   Elemcount output_index = 0, array_index = 0;
@@ -5119,10 +5192,8 @@
         }
 
       if (reverse_order ? 
-          !NILP (c_predicate (Fcar (list), array [array_index], predicate,
-                              key_func)) :
-          NILP (c_predicate (array [array_index], Fcar (list), predicate,
-                             key_func)))
+	  check_merge (predicate, key, Fcar (list), array [array_index]) :
+	  !check_merge (predicate, key, array [array_index], Fcar (list)))
         {
           output [output_index] = XCAR (list);
           list = XCDR (list);
@@ -5170,8 +5241,7 @@
 {
   Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2],
     predicate = args[3], result = Qnil;
-  Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object,
-			      Lisp_Object);
+  check_test_func_t check_merge = NULL;
 
   PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL);
 
@@ -5180,8 +5250,7 @@
 
   CHECK_KEY_ARGUMENT (key);
 
-  c_predicate = EQ (key, Qidentity) ?
-    c_merge_predicate_nokey : c_merge_predicate_key;
+  check_merge = get_merge_predicate (predicate, key);
 
   if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two)))
     {
@@ -5197,7 +5266,7 @@
         }
       else if (CONSP (sequence_one) && CONSP (sequence_two))
 	{
-	  result = list_merge (sequence_one, sequence_two, c_predicate,
+	  result = list_merge (sequence_one, sequence_two, check_merge,
                                predicate, key);
 	}
       else
@@ -5239,8 +5308,7 @@
 
           result = list_array_merge_into_list (sequence_one,
                                                array_storage, array_length,
-                                               c_predicate,
-                                               predicate, key,
+                                               check_merge, predicate, key,
                                                reverse_order);
         }
     }
@@ -5304,8 +5372,7 @@
         {
           list_list_merge_into_array (output + 1, output_len - 1,
                                       sequence_one, sequence_two,
-                                      c_predicate, predicate,
-                                      key);
+                                      check_merge, predicate, key);
         }
       else if (LISTP (sequence_one))
         {
@@ -5313,8 +5380,7 @@
                                        sequence_one,
                                        sequence_two_storage,
                                        sequence_two_len,
-                                       c_predicate, predicate,
-                                       key, 0);
+                                       check_merge, predicate, key, 0);
         }
       else if (LISTP (sequence_two))
         {
@@ -5322,15 +5388,14 @@
                                        sequence_two,
                                        sequence_one_storage,
                                        sequence_one_len,
-                                       c_predicate, predicate,
-                                       key, 1);
+                                       check_merge, predicate, key, 1);
         }
       else
         {
           array_merge (output + 1, output_len - 1,
                        sequence_one_storage, sequence_one_len,
                        sequence_two_storage, sequence_two_len,
-                       c_predicate, predicate,
+                       check_merge, predicate,
                        key);
         }
 
@@ -5347,13 +5412,9 @@
   return result;
 }
 
-/* The sort function should return non-nil if OBJ1 < OBJ2, nil otherwise.
-   NOTE: This is backwards from the way qsort() works. */
 Lisp_Object
-list_sort (Lisp_Object list,
-           Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 
-                                       Lisp_Object, Lisp_Object),
-           Lisp_Object predicate, Lisp_Object key_func)
+list_sort (Lisp_Object list, check_test_func_t check_merge,
+	   Lisp_Object predicate, Lisp_Object key)
 {
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object back, tem;
@@ -5363,29 +5424,22 @@
   if (XINT (len) < 2)
     return list;
 
-  if (NULL == c_predicate)
-    {
-      c_predicate = EQ (key_func, Qidentity) ? c_merge_predicate_nokey :
-        c_merge_predicate_key;
-    }
-
   len = make_int (XINT (len) / 2 - 1);
   tem = Fnthcdr (len, list);
   back = Fcdr (tem);
   Fsetcdr (tem, Qnil);
 
-  GCPRO4 (front, back, predicate, key_func);
-  front = list_sort (front, c_predicate, predicate, key_func);
-  back = list_sort (back, c_predicate, predicate, key_func);
-
-  RETURN_UNGCPRO (list_merge (front, back, c_predicate, predicate, key_func));
+  GCPRO4 (front, back, predicate, key);
+  front = list_sort (front, check_merge, predicate, key);
+  back = list_sort (back, check_merge, predicate, key);
+
+  RETURN_UNGCPRO (list_merge (front, back, check_merge, predicate, key));
 }
 
 static void
 array_sort (Lisp_Object *array, Elemcount array_len,
-            Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 
-                                        Lisp_Object, Lisp_Object),
-            Lisp_Object predicate, Lisp_Object key_func)
+	    check_test_func_t check_merge,
+	    Lisp_Object predicate, Lisp_Object key)
 {
   Elemcount split;
 
@@ -5394,11 +5448,11 @@
 
   split = array_len / 2;
 
-  array_sort (array, split, c_predicate, predicate, key_func);
-  array_sort (array + split, array_len - split, c_predicate, predicate,
-	      key_func);
+  array_sort (array, split, check_merge, predicate, key);
+  array_sort (array + split, array_len - split, check_merge, predicate,
+	      key);
   array_merge (array, array_len, array, split, array + split,
-	       array_len - split, c_predicate, predicate, key_func);
+	       array_len - split, check_merge, predicate, key);
 }            
 
 DEFUN ("sort*", FsortX, 2, MANY, 0, /*
@@ -5421,8 +5475,7 @@
 {
   Lisp_Object sequence = args[0], predicate = args[1];
   Lisp_Object *sequence_carray;
-  Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object,
-                              Lisp_Object);
+  check_test_func_t check_merge = NULL;
   Elemcount sequence_len, i;
 
   PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL);
@@ -5431,17 +5484,16 @@
 
   CHECK_KEY_ARGUMENT (key);
 
-  c_predicate = EQ (key, Qidentity) ?
-    c_merge_predicate_nokey : c_merge_predicate_key;
+  check_merge = get_merge_predicate (predicate, key);
 
   if (LISTP (sequence))
     {
-      sequence = list_sort (sequence, c_predicate, predicate, key);
+      sequence = list_sort (sequence, check_merge, predicate, key);
     }
   else if (VECTORP (sequence))
     {
       array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence),
-                  c_predicate, predicate, key);
+                  check_merge, predicate, key);
     }
   else if (STRINGP (sequence))
     {
@@ -5452,7 +5504,7 @@
       STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len);
 
       /* No GCPRO necessary, characters are immediate. */
-      array_sort (sequence_carray, sequence_len, c_predicate, predicate, key);
+      array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
 
       strdata = XSTRING_DATA (sequence);
 
@@ -5474,7 +5526,7 @@
       BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len);
 
       /* No GCPRO necessary, bits are immediate. */
-      array_sort (sequence_carray, sequence_len, c_predicate, predicate, key);
+      array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
 
       for (i = 0; i < sequence_len; ++i)
         {
@@ -11696,6 +11748,7 @@
   DEFSYMBOL (Qintersection);
   DEFSYMBOL (Qnintersection);
   DEFSYMBOL (Qsubsetp);
+  DEFSYMBOL (Qcar_less_than_car);
   DEFSYMBOL (Qset_difference);
   DEFSYMBOL (Qnset_difference);
   DEFSYMBOL (Qnunion);
--- a/src/fontcolor-msw.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/fontcolor-msw.c	Mon Feb 07 21:22:17 2011 +0100
@@ -1196,10 +1196,9 @@
    "family::::charset" for TrueType fonts, "family::size::charset"
    otherwise. */
 
-static Lisp_Object
-sort_font_list_function (Lisp_Object obj1, Lisp_Object obj2,
-			 Lisp_Object UNUSED (pred),
-                         Lisp_Object UNUSED (key_function))
+static Boolint
+sort_font_list_function (Lisp_Object UNUSED (pred), Lisp_Object UNUSED (key),
+			 Lisp_Object obj1, Lisp_Object obj2)
 {
   Ibyte *font1, *font2;
   Ibyte *c1, *c2;
@@ -1213,16 +1212,16 @@
     5. Courier New over other families.
   */
 
-  /* The sort function should return non-nil if OBJ1 < OBJ2, nil otherwise.
-     NOTE: This is backwards from the way qsort() works. */
+  /* The sort function should return non-zero if OBJ1 < OBJ2, zero
+     otherwise. */
 
   t1 = !NILP (XCDR (obj1));
   t2 = !NILP (XCDR (obj2));
 
   if (t1 && !t2)
-    return Qt;
+    return 1;
   if (t2 && !t1)
-    return Qnil;
+    return 0;
 
   font1 = XSTRING_DATA (XCAR (obj1));
   font2 = XSTRING_DATA (XCAR (obj2));
@@ -1234,9 +1233,9 @@
   t2 = !qxestrcasecmp_ascii (c2 + 1, "western");
 
   if (t1 && !t2)
-    return Qt;
+    return 1;
   if (t2 && !t1)
-    return Qnil;
+    return 0;
 
   c1 -= 2;
   c2 -= 2;
@@ -1244,9 +1243,9 @@
   t2 = *c2 == ':';
 
   if (t1 && !t2)
-    return Qt;
+    return 1;
   if (t2 && !t1)
-    return Qnil;
+    return 0;
 
   if (!t1 && !t2)
     {
@@ -1259,25 +1258,25 @@
       t2 = qxeatoi (c2 + 1) - 10;
 
       if (abs (t1) < abs (t2))
-	return Qt;
+	return 1;
       else if (abs (t2) < abs (t1))
-	return Qnil;
+	return 0;
       else if (t1 < t2)
 	/* Prefer a smaller font over a larger one just as far away
 	   because the smaller one won't upset the total line height if it's
 	   just a few chars. */
-	return Qt;
+	return 1;
     }
 
   t1 = !qxestrncasecmp_ascii (font1, "courier new:", 12);
   t2 = !qxestrncasecmp_ascii (font2, "courier new:", 12);
 
   if (t1 && !t2)
-    return Qt;
+    return 1;
   if (t2 && !t1)
-    return Qnil;
+    return 0;
 
-  return Qnil;
+  return 0;
 }
 
 /*
--- a/src/intl-win32.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/intl-win32.c	Mon Feb 07 21:22:17 2011 +0100
@@ -2356,14 +2356,15 @@
   Fmake_coding_system_internal
     (Qmswindows_unicode, Qunicode,
      build_defer_string ("MS Windows Unicode"),
-     nconc2 (list4 (Qdocumentation,
-		    build_defer_string (
+     listu (Qdocumentation,
+            build_defer_string (
 "Converts to the Unicode encoding for Windows API calls.\n"
 "This encoding is equivalent to standard UTF16, little-endian."
 ),
-		    Qmnemonic, build_ascstring ("MSW-U")),
-	     list4 (Qunicode_type, Qutf_16,
-		    Qlittle_endian, Qt)));
+            Qmnemonic, build_ascstring ("MSW-U"),
+            Qunicode_type, Qutf_16,
+            Qlittle_endian, Qt,
+            Qunbound));
 
 #ifdef MULE
   /* Just temporarily.  This will get fixed in mule-msw-init.el. */
--- a/src/keymap.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/keymap.c	Mon Feb 07 21:22:17 2011 +0100
@@ -735,10 +735,9 @@
   return 0;
 }
 
-static Lisp_Object map_keymap_sort_predicate (Lisp_Object obj1,
-                                              Lisp_Object obj2,
-                                              Lisp_Object pred,
-                                              Lisp_Object key_func);
+static Boolint map_keymap_sort_predicate (Lisp_Object pred, Lisp_Object key,
+					  Lisp_Object obj1, Lisp_Object obj2);
+					  
 
 static Lisp_Object
 keymap_submaps (Lisp_Object keymap)
@@ -762,7 +761,7 @@
 		     &keymap_submaps_closure);
       /* keep it sorted so that the result of accessible-keymaps is ordered */
       k->sub_maps_cache = list_sort (result, map_keymap_sort_predicate,
-                                     Qnil, Qidentity);
+                                     Qnil, Qnil);
       UNGCPRO;
     }
   return k->sub_maps_cache;
@@ -2894,10 +2893,9 @@
 /* used by map_keymap_sorted(), describe_map_sort_predicate(),
    and keymap_submaps().
  */
-static Lisp_Object
-map_keymap_sort_predicate (Lisp_Object obj1, Lisp_Object obj2,
-                           Lisp_Object UNUSED (pred),
-                           Lisp_Object UNUSED (key_func))
+static Boolint
+map_keymap_sort_predicate (Lisp_Object UNUSED (pred), Lisp_Object UNUSED (key),
+			   Lisp_Object obj1, Lisp_Object obj2)
 {
   /* obj1 and obj2 are conses with keysyms in their cars.  Cdrs are ignored.
    */
@@ -2910,12 +2908,12 @@
   obj2 = XCAR (obj2);
 
   if (EQ (obj1, obj2))
-    return Qnil;
+    return 0;
   bit1 = MODIFIER_HASH_KEY_BITS (obj1);
   bit2 = MODIFIER_HASH_KEY_BITS (obj2);
 
-  /* If either is a symbol with a Qcharacter_of_keysym property, then sort it by
-     that code instead of alphabetically.
+  /* If either is a symbol with a Qcharacter_of_keysym property, then sort
+     it by that code instead of alphabetically.
      */
   if (! bit1 && SYMBOLP (obj1))
     {
@@ -2940,7 +2938,7 @@
 
   /* all symbols (non-ASCIIs) come after characters (ASCIIs) */
   if (XTYPE (obj1) != XTYPE (obj2))
-    return SYMBOLP (obj2) ? Qt : Qnil;
+    return SYMBOLP (obj2);
 
   if (! bit1 && CHARP (obj1)) /* they're both ASCII */
     {
@@ -2948,24 +2946,24 @@
       int o2 = XCHAR (obj2);
       if (o1 == o2 &&		/* If one started out as a symbol and the */
 	  sym1_p != sym2_p)	/* other didn't, the symbol comes last. */
-	return sym2_p ? Qt : Qnil;
-
-      return o1 < o2 ? Qt : Qnil;	/* else just compare them */
+	return sym2_p;
+
+      return o1 < o2;		/* else just compare them */
     }
 
   /* else they're both symbols.  If they're both buckys, then order them. */
   if (bit1 && bit2)
-    return bit1 < bit2 ? Qt : Qnil;
+    return bit1 < bit2;
 
   /* if only one is a bucky, then it comes later */
   if (bit1 || bit2)
-    return bit2 ? Qt : Qnil;
+    return bit2;
 
   /* otherwise, string-sort them. */
   {
     Ibyte *s1 = XSTRING_DATA (XSYMBOL (obj1)->name);
     Ibyte *s2 = XSTRING_DATA (XSYMBOL (obj2)->name);
-    return 0 > qxestrcmp (s1, s2) ? Qt : Qnil;
+    return 0 > qxestrcmp (s1, s2);
   }
 }
 
@@ -4085,10 +4083,10 @@
 			    *(closure->list));
 }
 
-
-static Lisp_Object
-describe_map_sort_predicate (Lisp_Object obj1, Lisp_Object obj2,
-			     Lisp_Object pred, Lisp_Object key_func)
+static Boolint
+describe_map_sort_predicate (Lisp_Object pred, Lisp_Object key_func,
+			     Lisp_Object obj1, Lisp_Object obj2)
+			     
 {
   /* obj1 and obj2 are conses of the form
      ( ( <keysym> . <modifiers> ) . <binding> )
@@ -4100,9 +4098,9 @@
   bit1 = XINT (XCDR (obj1));
   bit2 = XINT (XCDR (obj2));
   if (bit1 != bit2)
-    return bit1 < bit2 ? Qt : Qnil;
+    return bit1 < bit2;
   else
-    return map_keymap_sort_predicate (obj1, obj2, pred, key_func);
+    return map_keymap_sort_predicate (pred, key_func, obj1, obj2);
 }
 
 /* Elide 2 or more consecutive numeric keysyms bound to the same thing,
@@ -4210,7 +4208,7 @@
 
   if (!NILP (list))
     {
-      list = list_sort (list, describe_map_sort_predicate, Qnil, Qidentity);
+      list = list_sort (list, describe_map_sort_predicate, Qnil, Qnil);
       buffer_insert_ascstring (buf, "\n");
       while (!NILP (list))
 	{
--- a/src/lisp.h	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/lisp.h	Mon Feb 07 21:22:17 2011 +0100
@@ -4720,6 +4720,10 @@
                                                      Lisp_Object, int,
                                                      Lisp_Object, Lisp_Object));
 
+MODULE_API DECLARE_DOESNT_RETURN (throw_or_bomb_out_unsafe (Lisp_Object,
+							    Lisp_Object, int,
+							    Lisp_Object, Lisp_Object));
+
 MODULE_API DECLARE_DOESNT_RETURN (signal_error_1 (Lisp_Object, Lisp_Object));
 void maybe_signal_error_1 (Lisp_Object, Lisp_Object, Lisp_Object,
 			   Error_Behavior);
@@ -5242,15 +5246,19 @@
 EXFUN (Fsubseq, 3);
 EXFUN (Fvalid_plist_p, 1);
 
+extern Boolint check_lss_key_car (Lisp_Object, Lisp_Object, Lisp_Object,
+				  Lisp_Object);
+extern Boolint check_string_lessp_nokey (Lisp_Object, Lisp_Object,
+					 Lisp_Object, Lisp_Object);
+
+typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key,
+				      Lisp_Object item, Lisp_Object elt);
+
 Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
-                        Lisp_Object (*c_predicate) (Lisp_Object o1,
-                                                    Lisp_Object o2,
-                                                    Lisp_Object pred,
-                                                    Lisp_Object keyf),
+			check_test_func_t check_merge,
                         Lisp_Object predicate, Lisp_Object key_func);
 Lisp_Object list_sort (Lisp_Object list,
-                       Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 
-                                                   Lisp_Object, Lisp_Object),
+		       check_test_func_t check_merge,
                        Lisp_Object predicate, Lisp_Object key_func);
 
 void bump_string_modiff (Lisp_Object);
--- a/src/profile.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/profile.c	Mon Feb 07 21:22:17 2011 +0100
@@ -540,15 +540,16 @@
       unbind_to (count);
     }
 
-  retv = nconc2 (list6 (Qtiming, closure.timing, Qtotal_timing,
-			copy_hash_table_or_blank (Vtotal_timing_profile_table),
-			Qcall_count,
-			copy_hash_table_or_blank (Vcall_count_profile_table)),
-		 list4 (Qgc_usage,
-			copy_hash_table_or_blank (Vgc_usage_profile_table),
-			Qtotal_gc_usage,
-			copy_hash_table_or_blank (Vtotal_gc_usage_profile_table
-						  )));
+  retv = listu (Qtiming, closure.timing,
+                Qtotal_timing,
+                copy_hash_table_or_blank (Vtotal_timing_profile_table),
+                Qcall_count,
+                copy_hash_table_or_blank (Vcall_count_profile_table),
+                Qgc_usage,
+                copy_hash_table_or_blank (Vgc_usage_profile_table),
+                Qtotal_gc_usage,
+                copy_hash_table_or_blank (Vtotal_gc_usage_profile_table),
+                Qunbound);
   unbind_to (depth);
   return retv;
 }
--- a/src/redisplay.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/redisplay.c	Mon Feb 07 21:22:17 2011 +0100
@@ -6686,12 +6686,25 @@
   unbind_to (depth);
 }
 
+static int the_ritual_suicide_has_been_cancelled = 0;
+
+void
+redisplay_cancel_ritual_suicide(void)
+{
+  the_ritual_suicide_has_been_cancelled = 1;
+}
+
 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS
 
 static Lisp_Object
 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe))
 {
-  assert (!in_display);
+  if (!the_ritual_suicide_has_been_cancelled)
+    {
+      assert (!in_display);
+    }
+  else
+    the_ritual_suicide_has_been_cancelled = 0;
   return Qnil;
 }
 
--- a/src/redisplay.h	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/redisplay.h	Mon Feb 07 21:22:17 2011 +0100
@@ -846,4 +846,6 @@
 int enter_redisplay_critical_section_if (Boolint from_outside);
 void exit_redisplay_critical_section_if (Boolint from_outside, int depth);
 
+void redisplay_cancel_ritual_suicide(void);
+
 #endif /* INCLUDED_redisplay_h_ */
--- a/src/symbols.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/symbols.c	Mon Feb 07 21:22:17 2011 +0100
@@ -506,8 +506,8 @@
   closure.accumulation = Qnil;
   GCPRO1 (closure.accumulation);
   map_obarray (Vobarray, apropos_mapper, &closure);
-  closure.accumulation = list_sort (closure.accumulation, NULL, Qstring_lessp,
-                                    Qidentity);
+  closure.accumulation = list_sort (closure.accumulation,
+				    check_string_lessp_nokey, Qnil, Qnil);
   UNGCPRO;
   return closure.accumulation;
 }
--- a/src/unicode.c	Sat Jan 22 00:59:20 2011 +0100
+++ b/src/unicode.c	Mon Feb 07 21:22:17 2011 +0100
@@ -3292,8 +3292,8 @@
   Fmake_coding_system_internal
     (Qutf_8, Qunicode,
      build_defer_string ("UTF-8"),
-     nconc2 (list4 (Qdocumentation,
-		    build_defer_string (
+     listu (Qdocumentation,
+            build_defer_string (
 "UTF-8 Unicode encoding -- ASCII-compatible 8-bit variable-width encoding\n"
 "sharing the following principles with the Mule-internal encoding:\n"
 "\n"
@@ -3315,6 +3315,7 @@
 "  -- Given only the leading byte, you know how many following bytes\n"
 "     are present.\n"
 ),
-		    Qmnemonic, build_ascstring ("UTF8")),
-	     list2 (Qunicode_type, Qutf_8)));
+            Qmnemonic, build_ascstring ("UTF8"),
+            Qunicode_type, Qutf_8,
+            Qunbound));
 }
--- a/tests/ChangeLog	Sat Jan 22 00:59:20 2011 +0100
+++ b/tests/ChangeLog	Mon Feb 07 21:22:17 2011 +0100
@@ -1,3 +1,25 @@
+2011-02-07  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* automated/lisp-tests.el:
+	Test lexical scope for `block', `return-from'; add a
+	Known-Bug-Expect-Failure for a contorted example that fails when
+	byte-compiled.
+
+2011-01-23  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* automated/lisp-tests.el:
+	When sanity-checking :start and :end keyword arguments, loop at
+	macroexpansion time, not runtime, allowing us to pick up any
+	compiler macros and giving a clearer *Test-Log* buffer.
+
+2011-01-23  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* automated/lisp-tests.el (test-fun):
+	#'delete* and friends can now throw a wrong-type-argument if
+	handed a non-sequence; accept this too when checking for an error
+	when passing a fixnum as the SEQUENCE argument.
+	Check #'remove*, #'remove and #'remq too.
+
 2011-01-15  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* automated/lisp-tests.el (list): Test #'concatenate, especially
--- a/tests/automated/lisp-tests.el	Sat Jan 22 00:59:20 2011 +0100
+++ b/tests/automated/lisp-tests.el	Mon Feb 07 21:22:17 2011 +0100
@@ -791,19 +791,21 @@
       `(progn
 	 (Check-Error wrong-number-of-arguments (,fun))
 	 (Check-Error wrong-number-of-arguments (,fun nil))
-	 (Check-Error malformed-list (,fun nil 1))
+	 (Check-Error (malformed-list wrong-type-argument) (,fun nil 1))
 	 ,@(loop for n in '(1 2 2000)
 	     collect `(Check-Error circular-list (,fun 1 (make-circular-list ,n))))))
      (test-funs (&rest funs) `(progn ,@(loop for fun in funs collect `(test-fun ,fun)))))
 
-  (test-funs member* member old-member 
-	     memq   old-memq
-	     assoc* assoc  old-assoc
-	     rassoc* rassoc old-rassoc
-	     rassq  old-rassq
-	     delete* delete old-delete
-	     delq   old-delq
-	     remassoc remassq remrassoc remrassq))
+  (test-funs member* member memq 
+             assoc* assoc assq 
+             rassoc* rassoc rassq 
+             delete* delete delq 
+             remove* remove remq 
+             old-member old-memq 
+             old-assoc old-assq 
+             old-rassoc old-rassq 
+             old-delete old-delq 
+             remassoc remassq remrassoc remrassq))
 
 (let ((x '((1 . 2) 3 (4 . 5))))
   (Assert (eq (assoc  1 x) (car x)))
@@ -2678,115 +2680,154 @@
         (string (make-string string-length
                              (or (decode-char 'ucs #x20ac) ?\xFF)))
         (item 'cons))
-    (dolist (function '(count position find delete* remove* reduce))
-      (Check-Error args-out-of-range
-                   (funcall function item list
-                            :start (1+ list-length) :end (1+ list-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function item list
-                            :start -1 :end list-length))
-      (Check-Error args-out-of-range
-                   (funcall function item list :end (* 2 list-length)))
-      (Check-Error args-out-of-range
-                   (funcall function item vector
-                            :start (1+ vector-length) :end (1+ vector-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function item vector :start -1))
-      (Check-Error args-out-of-range
-                   (funcall function item vector :end (* 2 vector-length)))
-      (Check-Error args-out-of-range
-                   (funcall function item bit-vector
-                            :start (1+ vector-length) :end (1+ vector-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function item bit-vector :start -1))
-      (Check-Error args-out-of-range
-                   (funcall function item bit-vector :end (* 2 vector-length)))
-      (Check-Error args-out-of-range
-                   (funcall function item string
-                            :start (1+ string-length) :end (1+ string-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function item string :start -1))
-      (Check-Error args-out-of-range
-                   (funcall function item string :end (* 2 string-length))))
-    (dolist (function '(delete-duplicates remove-duplicates))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence list)
-                            :start (1+ list-length) :end (1+ list-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence list)
-                            :start -1 :end list-length))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence list)
-                            :end (* 2 list-length)))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence vector)
-                            :start (1+ vector-length) :end (1+ vector-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence vector) :start -1))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence vector)
-                            :end (* 2 vector-length)))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence bit-vector)
-                            :start (1+ vector-length) :end (1+ vector-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence bit-vector) :start -1))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence bit-vector)
-                            :end (* 2 vector-length)))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence string)
-                            :start (1+ string-length) :end (1+ string-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence string) :start -1))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence string)
-                            :end (* 2 string-length))))
-    (dolist (function '(replace mismatch search))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence list) (copy-sequence list)
-                            :start1 (1+ list-length) :end1 (1+ list-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence list) (copy-sequence list)
-                            :start1 -1 :end1 list-length))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence list) (copy-sequence list)
-                            :end1 (* 2 list-length)))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence vector)
-                            (copy-sequence vector) :start1 (1+ vector-length)
-                            :end1 (1+ vector-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence vector)
-                            (copy-sequence vector) :start1 -1))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence vector)
-                            (copy-sequence vector)
-                            :end1 (* 2 vector-length)))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence bit-vector)
-                            (copy-sequence bit-vector)
-                            :start1 (1+ vector-length)
-                            :end1 (1+ vector-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence bit-vector)
-                            (copy-sequence bit-vector) :start1 -1))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence bit-vector)
-                            (copy-sequence bit-vector)
-                            :end1 (* 2 vector-length)))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence string)
-                            (copy-sequence string)
-                            :start1 (1+ string-length)
-                            :end1 (1+ string-length)))
-      (Check-Error wrong-type-argument
-                   (funcall function (copy-sequence string)
-                            (copy-sequence string) :start1 -1))
-      (Check-Error args-out-of-range
-                   (funcall function (copy-sequence string)
-                            (copy-sequence string)
-                            :end1 (* 2 string-length))))))
+    (macrolet
+        ((construct-item-sequence-checks (&rest functions)
+           (cons
+            'progn
+            (mapcan
+             #'(lambda (function)
+                 `((Check-Error args-out-of-range
+                                (,function item list
+                                           :start (1+ list-length)
+                                           :end (1+ list-length)))
+                   (Check-Error wrong-type-argument
+                                (,function item list :start -1
+                                           :end list-length))
+                   (Check-Error args-out-of-range
+                                (,function item list :end (* 2 list-length)))
+                   (Check-Error args-out-of-range
+                                (,function item vector
+                                           :start (1+ vector-length)
+                                           :end (1+ vector-length)))
+                   (Check-Error wrong-type-argument
+                                (,function item vector :start -1))
+                   (Check-Error args-out-of-range
+                                (,function item vector
+                                           :end (* 2 vector-length)))
+                   (Check-Error args-out-of-range
+                                (,function item bit-vector
+                                           :start (1+ vector-length)
+                                           :end (1+ vector-length)))
+                   (Check-Error wrong-type-argument
+                                (,function item bit-vector :start -1))
+                   (Check-Error args-out-of-range
+                                (,function item bit-vector
+                                           :end (* 2 vector-length)))
+                   (Check-Error args-out-of-range
+                                (,function item string
+                                           :start (1+ string-length)
+                                           :end (1+ string-length)))
+                   (Check-Error wrong-type-argument
+                                (,function item string :start -1))
+                   (Check-Error args-out-of-range
+                                (,function item string
+                                           :end (* 2 string-length)))))
+             functions)))
+         (construct-one-sequence-checks (&rest functions)
+           (cons
+            'progn
+            (mapcan
+             #'(lambda (function)
+                 `((Check-Error args-out-of-range
+                                (,function (copy-sequence list)
+                                           :start (1+ list-length)
+                                           :end (1+ list-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence list)
+                                           :start -1 :end list-length))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence list)
+                                           :end (* 2 list-length)))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence vector)
+                                           :start (1+ vector-length)
+                                           :end (1+ vector-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence vector) :start -1))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence vector)
+                                           :end (* 2 vector-length)))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence bit-vector)
+                                           :start (1+ vector-length)
+                                           :end (1+ vector-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence bit-vector)
+                                           :start -1))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence bit-vector)
+                                           :end (* 2 vector-length)))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence string)
+                                           :start (1+ string-length)
+                                           :end (1+ string-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence string) :start -1))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence string)
+                                           :end (* 2 string-length)))))
+             functions)))
+         (construct-two-sequence-checks (&rest functions)
+           (cons
+            'progn
+            (mapcan
+             #'(lambda (function)
+                 `((Check-Error args-out-of-range
+                                (,function (copy-sequence list)
+                                           (copy-sequence list)
+                                           :start1 (1+ list-length)
+                                           :end1 (1+ list-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence list)
+                                           (copy-sequence list)
+                                           :start1 -1 :end1 list-length))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence list)
+                                           (copy-sequence list)
+                                           :end1 (* 2 list-length)))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence vector)
+                                           (copy-sequence vector)
+                                           :start1 (1+ vector-length)
+                                           :end1 (1+ vector-length)))
+                   (Check-Error wrong-type-argument
+                                (,function
+                                 (copy-sequence vector)
+                                 (copy-sequence vector) :start1 -1))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence vector)
+                                           (copy-sequence vector)
+                                           :end1 (* 2 vector-length)))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence bit-vector)
+                                           (copy-sequence bit-vector)
+                                           :start1 (1+ vector-length)
+                                           :end1 (1+ vector-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence bit-vector)
+                                           (copy-sequence bit-vector)
+                                           :start1 -1))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence bit-vector)
+                                           (copy-sequence bit-vector)
+                                           :end1 (* 2 vector-length)))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence string)
+                                           (copy-sequence string)
+                                           :start1 (1+ string-length)
+                                           :end1 (1+ string-length)))
+                   (Check-Error wrong-type-argument
+                                (,function (copy-sequence string)
+                                           (copy-sequence string) :start1 -1))
+                   (Check-Error args-out-of-range
+                                (,function (copy-sequence string)
+                                           (copy-sequence string)
+                                           :end1 (* 2 string-length)))))
+             functions))))
+      (construct-item-sequence-checks count position find delete* remove*
+                                      reduce)
+      (construct-one-sequence-checks delete-duplicates remove-duplicates)
+      (construct-two-sequence-checks replace mismatch search))))
 
 (let* ((list (list 1 2 3 4 5 6 7 120 'hi-there '#:everyone))
        (vector (map 'vector #'identity list))
@@ -2828,4 +2869,33 @@
 					 (subseq bit-vector 0 4)
 					 (append (subseq bit-vector 4) nil)))))
 
+;;-----------------------------------------------------
+;; Test `block', `return-from'
+;;-----------------------------------------------------
+(Assert (eql 1 (block outer
+		 (flet ((outtahere (n) (return-from outer n)))
+		   (block outer (outtahere 1)))
+		 2))
+	"checking `block' and `return-from' are lexically scoped correctly")
+
+;; Other tests are available in Paul Dietz' test suite, and pass. The above,
+;; which we used to fail, is based on a test in the Hyperspec. We still
+;; behave incorrectly when compiled for the contorted-example function of
+;; CLTL2, whence the following test:
+
+(flet ((needs-lexical-context (first second third)
+	 (if (eql 0 first)
+	     (funcall second)
+	   (block awkward
+	     (+ 5 (needs-lexical-context
+		   (1- first)
+		   third
+		   #'(lambda () (return-from awkward 0)))
+		first)))))
+  (if (compiled-function-p (symbol-function 'needs-lexical-context))
+      (Known-Bug-Expect-Failure
+       (Assert (eql 0 (needs-lexical-context 2 nil nil))
+	"the function special operator doesn't create a lexical context."))
+    (Assert (eql 0 (needs-lexical-context 2 nil nil)))))
+
 ;;; end of lisp-tests.el