changeset 4677:8f1ee2d15784

Support full Common Lisp multiple values in C. lisp/ChangeLog 2009-08-11 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el : Update this file to support full C-level multiple values. This involves: -- Four new bytecodes, and special compiler functions to compile multiple-value-call, multiple-value-list-internal, values, values-list, and, since it now needs to pass back multiple values and is a special form, throw. -- There's a new compiler variable, byte-compile-checks-on-load, which is a list of forms that are evaluated at the very start of a file, with an error thrown if any of them give nil. -- The header is now inserted *after* compilation, giving a chance for the compilation process to influence what those checks are. There is still a check done before compilation for non-ASCII characters, to try to turn off dynamic docstrings if appopriate, in `byte-compile-maybe-reset-coding'. Space is reserved for checks; comments describing the version of the byte compiler generating the file are inserted if space remains for them. * bytecomp.el (byte-compile-version): Update this, we're a newer version of the byte compiler. * byte-optimize.el (byte-optimize-funcall): Correct a comment. * bytecomp.el (byte-compile-lapcode): Discard the arg with byte-multiple-value-call. * bytecomp.el (byte-compile-checks-and-comments-space): New variable, describe how many octets to reserve for checks at the start of byte-compiled files. * cl-compat.el: Remove the fake multiple-value implementation. Have the functions that use it use the real multiple-value implementation instead. * cl-macs.el (cl-block-wrapper, cl-block-throw): Revise the byte-compile properties of these symbols to work now we've made throw into a special form; keep the byte-compile properties as anonymous lambdas, since we don't have docstrings for them. * cl-macs.el (multiple-value-bind, multiple-value-setq) (multiple-value-list, nth-value): Update these functions to work with the C support for multiple values. * cl-macs.el (values): Modify the setf handler for this to call #'multiple-value-list-internal appropriately. * cl-macs.el (cl-setf-do-store): If the store form is a cons, treat it specially as wrapping the store value. * cl.el (cl-block-wrapper): Make this an alias of #'and, not #'identity, since it needs to pass back multiple values. * cl.el (multiple-value-apply): We no longer support this, mark it obsolete. * lisp-mode.el (eval-interactive-verbose): Remove a useless space in the docstring. * lisp-mode.el (eval-interactive): Update this function and its docstring. It now passes back a list, basically wrapping any eval calls with multiple-value-list. This allows multiple values to be printed by default in *scratch*. * lisp-mode.el (prin1-list-as-multiple-values): New function, printing a list as multiple values in the manner of Bruno Haible's clisp, separating each entry with " ;\n". * lisp-mode.el (eval-last-sexp): Call #'prin1-list-as-multiple-values on the return value of #'eval-interactive. * lisp-mode.el (eval-defun): Call #'prin1-list-as-multiple-values on the return value of #'eval-interactive. * mouse.el (mouse-eval-sexp): Deal with lists corresponding to multiple values from #'eval-interactive. Call #'cl-prettyprint, which is always available, instead of sometimes calling #'pprint and sometimes falling back to prin1. * obsolete.el (obsolete-throw): New function, called from eval.c when #'funcall encounters an attempt to call #'throw (now a special form) as a function. Only needed for compatibility with 21.4 byte-code. man/ChangeLog addition: 2009-08-11 Aidan Kehoe <kehoea@parhasard.net> * cl.texi (Organization): Remove references to the obsolete multiple-value emulating code. src/ChangeLog addition: 2009-08-11 Aidan Kehoe <kehoea@parhasard.net> * bytecode.c (enum Opcode /* Byte codes */): Add four new bytecodes, to deal with multiple values. (POP_WITH_MULTIPLE_VALUES): New macro. (POP): Modify this macro to ignore multiple values. (DISCARD_PRESERVING_MULTIPLE_VALUES): New macro. (DISCARD): Modify this macro to ignore multiple values. (TOP_WITH_MULTIPLE_VALUES): New macro. (TOP_ADDRESS): New macro. (TOP): Modify this macro to ignore multiple values. (TOP_LVALUE): New macro. (Bcall): Ignore multiple values where appropriate. (Breturn): Pass back multiple values. (Bdup): Preserve multiple values. Use TOP_LVALUE with most bytecodes that assign anything to anything. (Bbind_multiple_value_limits, Bmultiple_value_call, Bmultiple_value_list_internal, Bthrow): Implement the new bytecodes. (Bgotoifnilelsepop, Bgotoifnonnilelsepop, BRgotoifnilelsepop, BRgotoifnonnilelsepop): Discard any multiple values. * callint.c (Fcall_interactively): Ignore multiple values when calling #'eval, in two places. * device-x.c (x_IO_error_handler): * macros.c (pop_kbd_macro_event): * eval.c (Fsignal): * eval.c (flagged_a_squirmer): Call throw_or_bomb_out, not Fthrow, now that the latter is a special form. * eval.c: Make Qthrow, Qobsolete_throw available as symbols. Provide multiple_value_current_limit, multiple-values-limit (the latter as specified by Common Lisp. * eval.c (For): Ignore multiple values when comparing with Qnil, but pass any multiple values back for the last arg. * eval.c (Fand): Ditto. * eval.c (Fif): Ignore multiple values when examining the result of the condition. * eval.c (Fcond): Ignore multiple values when comparing what the clauses give, but pass them back if a clause gave non-nil. * eval.c (Fprog2): Never pass back multiple values. * eval.c (FletX, Flet): Ignore multiple when evaluating what exactly symbols should be bound to. * eval.c (Fwhile): Ignore multiple values when evaluating the test. * eval.c (Fsetq, Fdefvar, Fdefconst): Ignore multiple values. * eval.c (Fthrow): Declare this as a special form; ignore multiple values for TAG, preserve them for VALUE. * eval.c (throw_or_bomb_out): Make this available to other files, now Fthrow is a special form. * eval.c (Feval): Ignore multiple values when calling a compiled function, a non-special-form subr, or a lambda expression. * eval.c (Ffuncall): If we attempt to call #'throw (now a special form) as a function, don't error, call #'obsolete-throw instead. * eval.c (make_multiple_value, multiple_value_aset) (multiple_value_aref, print_multiple_value, mark_multiple_value) (size_multiple_value): Implement the multiple_value type. Add a long comment describing our implementation. * eval.c (bind_multiple_value_limits): New function, used by the bytecode and by #'multiple-value-call, #'multiple-value-list-internal. * eval.c (multiple_value_call): New function, used by the bytecode and #'multiple-value-call. * eval.c (Fmultiple_value_call): New special form. * eval.c (multiple_value_list_internal): New function, used by the byte code and #'multiple-value-list-internal. * eval.c (Fmultiple_value_list_internal, Fmultiple_value_prog1): New special forms. * eval.c (Fvalues, Fvalues_list): New Lisp functions. * eval.c (values2): New function, for C code returning multiple values. * eval.c (syms_of_eval): Make our new Lisp functions and symbols available. * eval.c (multiple-values-limit): Make this available to Lisp. * event-msw.c (dde_eval_string): * event-stream.c (execute_help_form): * glade.c (connector): * glyphs-widget.c (glyph_instantiator_to_glyph): * glyphs.c (evaluate_xpm_color_symbols): * gui-x.c (wv_set_evalable_slot, button_item_to_widget_value): * gui.c (gui_item_value, gui_item_display_flush_left): * lread.c (check_if_suppressed): * menubar-gtk.c (menu_convert, menu_descriptor_to_widget_1): * menubar-msw.c (populate_menu_add_item): * print.c (Fwith_output_to_temp_buffer): * symbols.c (Fsetq_default): Ignore multiple values when calling Feval. * symeval.h: Add the header declarations necessary for the multiple-values implementation. * inline.c: #include symeval.h, now that it has some inline functions. * lisp.h: Update Fthrow's declaration. Make throw_or_bomb_out available to all files. * lrecord.h (enum lrecord_type): Add the multiple_value type here.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 16 Aug 2009 20:55:49 +0100
parents e3feb329bda9
children b5e1d4f6b66f
files lisp/ChangeLog lisp/byte-optimize.el lisp/bytecomp.el lisp/cl-compat.el lisp/cl-macs.el lisp/cl.el lisp/lisp-mode.el lisp/mouse.el lisp/obsolete.el man/ChangeLog man/cl.texi src/ChangeLog src/bytecode.c src/callint.c src/device-x.c src/eval.c src/event-msw.c src/event-stream.c src/glade.c src/glyphs-widget.c src/glyphs.c src/gui-x.c src/gui.c src/inline.c src/lisp.h src/lread.c src/lrecord.h src/macros.c src/menubar-gtk.c src/menubar-msw.c src/print.c src/symbols.c src/symeval.h
diffstat 33 files changed, 1609 insertions(+), 479 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/ChangeLog	Sun Aug 16 20:55:49 2009 +0100
@@ -10,6 +10,83 @@
 	Use buffer (format " *Minibuf-%d*" (minibuffer-depth)), regardless
 	of depth. 
 
+2009-08-11  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* bytecomp.el :
+	Update this file to support full C-level multiple values. This
+	involves:
+	-- Four new bytecodes, and special compiler functions to compile
+	multiple-value-call, multiple-value-list-internal, values,
+	values-list, and, since it now needs to pass back multiple values
+	and is a special form, throw. 
+	-- There's a new compiler variable, byte-compile-checks-on-load,
+	which is a list of forms that are evaluated at the very start of a
+	file, with an error thrown if any of them give nil. 
+	-- The header is now inserted *after* compilation, giving a chance
+	for the compilation process to influence what those checks
+	are. There is still a check done before compilation for non-ASCII
+	characters, to try to turn off dynamic docstrings if appopriate,
+	in `byte-compile-maybe-reset-coding'.
+	Space is reserved for checks; comments describing the version of
+	the byte compiler generating the file are inserted if space
+	remains for them.
+	* bytecomp.el (byte-compile-version): 
+	Update this, we're a newer version of the byte compiler.
+	* byte-optimize.el (byte-optimize-funcall): 
+	Correct a comment.
+	* bytecomp.el (byte-compile-lapcode): 
+	Discard the arg with byte-multiple-value-call.
+	* bytecomp.el (byte-compile-checks-and-comments-space): 
+	New variable, describe how many octets to reserve for checks at
+	the start of byte-compiled files. 
+	* cl-compat.el: 
+	Remove the fake multiple-value implementation. Have the functions
+	that use it use the real multiple-value implementation instead. 
+	* cl-macs.el (cl-block-wrapper, cl-block-throw): 
+	Revise the byte-compile properties of these symbols to work now
+	we've made throw into a special form; keep the byte-compile
+	properties as anonymous lambdas, since we don't have docstrings
+	for them. 
+	* cl-macs.el (multiple-value-bind, multiple-value-setq)
+	(multiple-value-list, nth-value): 
+	Update these functions to work with the C support for multiple
+	values.
+	* cl-macs.el (values): 
+	Modify the setf handler for this to call
+	#'multiple-value-list-internal appropriately.
+	* cl-macs.el (cl-setf-do-store): 
+	If the store form is a cons, treat it specially as wrapping the
+	store value.
+	* cl.el (cl-block-wrapper): 
+	Make this an alias of #'and, not #'identity, since it needs to
+	pass back multiple values.
+	* cl.el (multiple-value-apply): 
+	We no longer support this, mark it obsolete. 
+	* lisp-mode.el (eval-interactive-verbose): 
+	Remove a useless space in the docstring. 
+	* lisp-mode.el (eval-interactive): 
+	Update this function and its docstring. It now passes back a list,
+	basically wrapping any eval calls with multiple-value-list. This
+	allows multiple values to be printed by default in *scratch*. 
+	* lisp-mode.el (prin1-list-as-multiple-values): 
+	New function, printing a list as multiple values in the manner of
+	Bruno Haible's clisp, separating each entry with " ;\n".
+	* lisp-mode.el (eval-last-sexp):
+	Call #'prin1-list-as-multiple-values on the return value of
+	#'eval-interactive. 
+	* lisp-mode.el (eval-defun): 
+	Call #'prin1-list-as-multiple-values on the return value of
+	#'eval-interactive. 
+	* mouse.el (mouse-eval-sexp): 
+	Deal with lists corresponding to multiple values from
+	#'eval-interactive. Call #'cl-prettyprint, which is always
+	available, instead of sometimes calling #'pprint and sometimes
+	falling back to prin1. 
+	* obsolete.el (obsolete-throw): 
+	New function, called from eval.c when #'funcall encounters an
+	attempt to call #'throw (now a special form) as a function. Only
+	needed for compatibility with 21.4 byte-code. 
+
 2009-08-10  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* help.el (function-arglist, function-documentation): 
--- a/lisp/byte-optimize.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/byte-optimize.el	Sun Aug 16 20:55:49 2009 +0100
@@ -1093,7 +1093,7 @@
 (put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer)
 
 (defun byte-optimize-funcall (form)
-  ;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...)
+  ;; (funcall #'(lambda ...) ...) ==> ((lambda ...) ...)
   ;; (funcall 'foo ...) ==> (foo ...)
   (let ((fn (nth 1 form)))
     (if (memq (car-safe fn) '(quote function))
--- a/lisp/bytecomp.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/bytecomp.el	Sun Aug 16 20:55:49 2009 +0100
@@ -10,7 +10,7 @@
 ;;	Richard Stallman <rms@gnu.org>
 ;; Keywords: internal lisp
 
-(defconst byte-compile-version "2.27 XEmacs; 2000-09-12.")
+(defconst byte-compile-version "2.28 XEmacs; 2009-08-09.")
 
 ;; This file is part of XEmacs.
 
@@ -215,7 +215,7 @@
     (load-library "bytecomp-runtime"))
 
 (eval-when-compile
-  (defvar byte-compile-single-version nil
+  (defvar byte-compile-single-version t
     "If this is true, the choice of emacs version (v19 or v20) byte-codes will
 be hard-coded into bytecomp when it compiles itself.  If the compiler itself
 is compiled with optimization, this causes a speedup.")
@@ -304,6 +304,10 @@
   "This is completely ignored.  It is only around for backwards
 compatibility.")
 
+(defvar byte-compile-checks-on-load '((featurep 'xemacs))
+  "A list of expressions to check when first loading a file. 
+Emacs will throw an error if any of them fail; checks will be made in
+reverse order.")
 
 ;; FSF enables byte-compile-dynamic-docstrings but not byte-compile-dynamic
 ;; by default.  This would be a reasonable conservative approach except
@@ -440,7 +444,7 @@
 on the specbind stack.  The cdr of each cell is an integer bitmask.")
 
 (defvar byte-compile-force-escape-quoted nil
-  "If non-nil, `byte-compile-insert-header' always adds a coding cookie.
+  "If t, `byte-compile-maybe-reset-coding' always chooses `escape-quoted'
 
 This is for situations where the byte compiler output file needs to be
 able to encode character values above ?\\xFF, but this cannot be
@@ -733,7 +737,10 @@
 (byte-defop 176 nil byte-concatN)
 (byte-defop 177 nil byte-insertN)
 
-;; unused: 178-181
+(byte-defop 178  1 byte-bind-multiple-value-limits)
+(byte-defop 179 -3 byte-multiple-value-list-internal)
+(byte-defop 180  0 byte-multiple-value-call)
+(byte-defop 181 -1 byte-throw)
 
 ;; these ops are new to v20
 (byte-defop 182 -1 byte-member)
@@ -833,6 +840,10 @@
 			       (<= (symbol-value op) byte-insertN))
 			  (setq pc (+ 2 pc))
 			  (cons off (cons (symbol-value op) bytes)))
+			 ((= byte-multiple-value-call (symbol-value op))
+			  (setq pc (1+ pc))
+			  ;; Ignore off. 
+			  (cons (symbol-value op) bytes))
 			 ((< off 6)
 			  (setq pc (1+ pc))
 			  (cons (+ (symbol-value op) off) bytes))
@@ -1386,6 +1397,8 @@
 	(byte-optimize byte-optimize)
 	(byte-compile-emacs19-compatibility
 	 byte-compile-emacs19-compatibility)
+	(byte-compile-checks-on-load
+	 byte-compile-checks-on-load)
 	(byte-compile-dynamic byte-compile-dynamic)
 	(byte-compile-dynamic-docstrings
 	 byte-compile-dynamic-docstrings)
@@ -1718,9 +1731,7 @@
 	;;				     byte-compile-warning-types
 	;;				   byte-compile-warnings))
         (byte-compile-force-escape-quoted byte-compile-force-escape-quoted)
-        (byte-compile-using-dynamic nil)
-        (byte-compile-using-escape-quoted nil)
-	)
+        (byte-compile-using-dynamic nil))
     (byte-compile-close-variables
      (save-excursion
        (setq byte-compile-outbuffer
@@ -1730,9 +1741,8 @@
        (setq case-fold-search nil)
        (and filename
 	    (not eval)
-	    (byte-compile-insert-header filename
-					byte-compile-inbuffer
-					byte-compile-outbuffer))
+	    (byte-compile-maybe-reset-coding byte-compile-inbuffer
+					     byte-compile-outbuffer))
        (setq byte-compile-using-dynamic
              (or (symbol-value-in-buffer 'byte-compile-dynamic
                                          byte-compile-inbuffer)
@@ -1763,6 +1773,8 @@
 
 	;; Compile pending forms at end of file.
 	(byte-compile-flush-pending)
+	(byte-compile-insert-header filename byte-compile-inbuffer
+				    byte-compile-outbuffer)
 	(byte-compile-warn-about-unresolved-functions)
 	;; Should we always do this?  When calling multiple files, it
 	;; would be useful to delay this warning until all have
@@ -1797,11 +1809,16 @@
       (kill-buffer byte-compile-outbuffer)
       nil)))
 
+(defvar byte-compile-checks-and-comments-space 475
+  "Number of octets of space for checks and comments; used by the dynamic
+docstrings code.")
+
 (defun byte-compile-insert-header (filename byte-compile-inbuffer
-					    byte-compile-outbuffer)
+				   byte-compile-outbuffer)
   (set-buffer byte-compile-inbuffer)
-  (let ((dynamic-docstrings byte-compile-dynamic-docstrings))
+  (let (checks-string comments)
     (set-buffer byte-compile-outbuffer)
+    (delete-region 1 (1+ byte-compile-checks-and-comments-space))
     (goto-char 1)
     ;;
     ;; The magic number of .elc files is ";ELC", or 0x3B454C43.  After that is
@@ -1817,62 +1834,56 @@
     (insert
      ";ELC"
      (if (byte-compile-version-cond byte-compile-emacs19-compatibility) 19 20)
-     "\000\000\000\n"
-     )
-    (insert ";;; compiled by "
-	    (or (and (boundp 'user-mail-address) user-mail-address)
-		(concat (user-login-name) "@" (system-name)))
-	    " on "
-	    (current-time-string) "\n;;; from file " filename "\n")
-    (insert ";;; emacs version " emacs-version ".\n")
-    (insert ";;; bytecomp version " byte-compile-version "\n;;; "
-     (cond
-       ((eq byte-optimize 'source) "source-level optimization only")
-       ((eq byte-optimize 'byte) "byte-level optimization only")
-       (byte-optimize "optimization is on")
-       (t "optimization is off"))
-     (if (byte-compile-version-cond byte-compile-emacs19-compatibility)
-	 "; compiled with Emacs 19 compatibility.\n"
-       ".\n"))
-   (if (not (byte-compile-version-cond byte-compile-emacs19-compatibility))
-       (insert ";;; this file uses opcodes which do not exist in Emacs 19.\n"
-	       ;; Have to check if emacs-version is bound so that this works
-	       ;; in files loaded early in loadup.el.
-	       "\n(if (and (boundp 'emacs-version)\n"
-	       "\t (or (and (boundp 'epoch::version) epoch::version)\n"
-	       "\t     (string-lessp emacs-version \"20\")))\n"
-	       "    (error \"`"
-	       ;; prin1-to-string is used to quote backslashes.
-	       (substring (prin1-to-string (file-name-nondirectory filename))
-			  1 -1)
-	       "' was compiled for Emacs 20\"))\n\n"))
-   (insert "(or (boundp 'current-load-list) (setq current-load-list nil))\n"
-	   "\n")
-   (if (and (byte-compile-version-cond byte-compile-emacs19-compatibility)
-	    dynamic-docstrings)
-       (insert ";;; this file uses opcodes which do not exist prior to\n"
-	       ";;; XEmacs 19.14/GNU Emacs 19.29 or later."
-	       ;; Have to check if emacs-version is bound so that this works
-	       ;; in files loaded early in loadup.el.
-	       "\n(if (and (boundp 'emacs-version)\n"
-	       "\t (or (and (boundp 'epoch::version) epoch::version)\n"
-	       "\t     (and (not (string-match \"XEmacs\" emacs-version))\n"
-	       "\t          (string-lessp emacs-version \"19.29\"))\n"
-	       "\t     (string-lessp emacs-version \"19.14\")))\n"
-	       "    (error \"`"
-	       ;; prin1-to-string is used to quote backslashes.
-	       (substring (prin1-to-string (file-name-nondirectory filename))
-			  1 -1)
-	       "' was compiled for XEmacs 19.14/Emacs 19.29 or later\"))\n\n"
-	       )
-      ))
-
-  ;; back in the inbuffer; determine and set the coding system for the .elc
-  ;; file if under Mule.  If there are any extended characters in the
-  ;; input file, use `escape-quoted' to make sure that both binary and
-  ;; extended characters are output properly and distinguished properly.
-  ;; Otherwise, use `raw-text' for maximum portability with non-Mule
-  ;; Emacsen.
+     "\000\000\000\n")
+    (when (not (eq (find-coding-system 'raw-text-unix)
+		   (find-coding-system buffer-file-coding-system)))
+      (insert (format ";;;###coding system: %s\n"
+		      (coding-system-name buffer-file-coding-system))))
+    (insert (format
+	     "\n(or %s\n    (error \"Loading this file requires: %s\"))\n"
+	     (setq checks-string
+		   (let ((print-readably t))
+		     (prin1-to-string (if (> (length 
+					      byte-compile-checks-on-load)
+					     1)
+					  (cons 'and
+						(reverse
+						 byte-compile-checks-on-load))
+					(car byte-compile-checks-on-load)))))
+	     checks-string))
+    (setq comments 
+	  (with-string-as-buffer-contents ""
+	    (insert "\n;;; compiled by "
+		    (or (and (boundp 'user-mail-address) user-mail-address)
+			(concat (user-login-name) "@" (system-name)))
+		    " on "
+		    (current-time-string) "\n;;; from file " filename "\n")
+	    (insert ";;; emacs version " emacs-version ".\n")
+	    (insert ";;; bytecomp version " byte-compile-version "\n;;; "
+		    (cond
+		     ((eq byte-optimize 'source)
+		      "source-level optimization only")
+		     ((eq byte-optimize 'byte) "byte-level optimization only")
+		     (byte-optimize "optimization is on")
+		     (t "optimization is off"))
+		    "\n")))
+
+    ;; We won't trip this unless the byte-compiler changes, in which case
+    ;; it's just a matter of upping the space. 
+    (assert (natnump (- (1+ byte-compile-checks-and-comments-space) (point)))
+	    t "Not enough space for the feature checks!")
+
+    (if (natnump (- (1+ byte-compile-checks-and-comments-space)
+		    (+ (point) (length comments))))
+	(insert comments))
+    (insert-char ?\  (- (1+ byte-compile-checks-and-comments-space)
+			(point)))))
+
+(defun byte-compile-maybe-reset-coding (byte-compile-inbuffer
+					byte-compile-outbuffer)
+  ;; We also reserve some space for the feature checks:
+  (goto-char 1)
+  (insert-char ?\  byte-compile-checks-and-comments-space)
   (if (or (featurep '(not mule)) ;; Don't scan buffer if we are not muleized
           (and
 	   (not byte-compile-force-escape-quoted)
@@ -1885,7 +1896,8 @@
 	     ;; not true of ordinary comments.
 	     (let ((non-latin-1-re
 		    (concat "[^\000-\377]" 
-			    #r"\|\\u[0-9a-fA-F]\{4,4\}\|\\U[0-9a-fA-F]\{8,8\}"))
+			    #r"\|\\u[0-9a-fA-F]\{4,4\}\|\\U[0-9a-fA-F]"
+			    "\\{8,8\\}"))
 		   (case-fold-search nil))
 	       (catch 'need-to-escape-quote
 		 (while (re-search-forward non-latin-1-re nil t)
@@ -1894,19 +1906,12 @@
 		   (forward-line 1))
 		 t)))))
       (setq buffer-file-coding-system 'raw-text-unix)
-    (insert "(or (featurep 'mule) (error \"Loading this file requires Mule support\"))
-;;;###coding system: escape-quoted\n")
     (setq buffer-file-coding-system 'escape-quoted)
-    ;; #### Lazy loading not yet implemented for MULE files
-    ;; mrb - Fix this someday.
+    (pushnew '(featurep 'mule) byte-compile-checks-on-load)
     (save-excursion
       (set-buffer byte-compile-inbuffer)
       (setq byte-compile-dynamic nil
-	    byte-compile-dynamic-docstrings nil))
-    ;;(external-debugging-output (prin1-to-string (buffer-local-variables))))
-    )
-  )
-
+	    byte-compile-dynamic-docstrings nil))))
 
 (defun byte-compile-output-file-form (form)
   ;; writes the given form to the output buffer, being careful of docstrings
@@ -3084,6 +3089,11 @@
 (byte-defop-compiler (% byte-rem)	2)
 (byte-defop-compiler aset		3)
 
+(byte-defop-compiler-1 bind-multiple-value-limits)
+(byte-defop-compiler multiple-value-list-internal)
+(byte-defop-compiler-1 multiple-value-call)
+(byte-defop-compiler throw)
+
 (byte-defop-compiler-rmsfun member	2)
 (byte-defop-compiler-rmsfun assq	2)
 
@@ -3102,11 +3112,14 @@
 ;;(byte-defop-compiler (mod byte-rem) 2)
 
 
-(defun byte-compile-subr-wrong-args (form n)
+(defun byte-compile-warn-wrong-args (form n)
   (when (memq 'subr-callargs byte-compile-warnings)
     (byte-compile-warn "%s called with %d arg%s, but requires %s"
 		       (car form) (length (cdr form))
-		       (if (= 1 (length (cdr form))) "" "s") n))
+		       (if (= 1 (length (cdr form))) "" "s") n)))
+
+(defun byte-compile-subr-wrong-args (form n)
+  (byte-compile-warn-wrong-args form n)
   ;; get run-time wrong-number-of-args error.
   (byte-compile-normal-call form))
 
@@ -3641,6 +3654,9 @@
 (byte-defop-compiler-1 inline byte-compile-progn)
 (byte-defop-compiler-1 progn)
 (byte-defop-compiler-1 prog1)
+(byte-defop-compiler-1 multiple-value-prog1)
+(byte-defop-compiler-1 values)
+(byte-defop-compiler-1 values-list)
 (byte-defop-compiler-1 prog2)
 (byte-defop-compiler-1 if)
 (byte-defop-compiler-1 cond)
@@ -3660,13 +3676,36 @@
 
 (defun byte-compile-prog1 (form)
   (setq form (cdr form))
+  ;; #'prog1 never returns multiple values:
+  (byte-compile-form-do-effect (list 'values (pop form)))
+  (byte-compile-body form t))
+
+(defun byte-compile-multiple-value-prog1 (form)
+  (setq form (cdr form))
   (byte-compile-form-do-effect (pop form))
   (byte-compile-body form t))
 
+(defun byte-compile-values (form)
+  (if (and (= 2 (length form))
+           (byte-compile-constp (second form)))
+      (byte-compile-form-do-effect (second form))
+    (byte-compile-normal-call form)))
+
+(defun byte-compile-values-list (form)
+  (if (and (= 2 (length form))
+           (or (null (second form))
+               (and (consp (second form))
+                    (eq (car (second form))
+                        'quote)
+                    (not (symbolp (car-safe (cdr (second form))))))))
+      (byte-compile-form-do-effect (car-safe (cdr (second form))))
+    (byte-compile-normal-call form)))
+
 (defun byte-compile-prog2 (form)
   (setq form (cdr form))
   (byte-compile-form (pop form) t)
-  (byte-compile-form-do-effect (pop form))
+  ;; #'prog2 never returns multiple values:
+  (byte-compile-form-do-effect (list 'values (pop form)))
   (byte-compile-body form t))
 
 (defmacro byte-compile-goto-if (cond discard tag)
@@ -3952,6 +3991,65 @@
   (byte-compile-body (cdr (cdr form)))
   (byte-compile-out 'byte-temp-output-buffer-show 0))
 
+(defun byte-compile-multiple-value-call (form)
+  (if (< (length form) 2)
+      (progn
+        (byte-compile-warn-wrong-args form 1)
+        (byte-compile-normal-call
+         `(signal 'wrong-number-of-arguments '(,(car form)
+                                               ,(length (cdr form))))))
+    (setq form (cdr form))
+    (byte-compile-form (car form))
+    (byte-compile-push-constant 0)
+    (byte-compile-variable-ref 'byte-varref 'multiple-values-limit)
+    ;; bind-multiple-value-limits leaves two existing values on the stack,
+    ;; and pushes a new value, the specpdl_depth() at the time it was
+    ;; called.
+    (byte-compile-out 'byte-bind-multiple-value-limits 0)
+    (mapcar 'byte-compile-form (cdr form))
+    ;; Most of the other code puts this sort of value in the program stream,
+    ;; not pushing it on the stack.
+    (byte-compile-push-constant (+ 3 (length form)))
+    (byte-compile-out 'byte-multiple-value-call (+ 3 (length form)))
+    (pushnew '(subrp (symbol-function 'multiple-value-call))
+             byte-compile-checks-on-load
+             :test #'equal)))
+
+(defun byte-compile-multiple-value-list-internal (form)
+  (if (/= 4 (length form))
+      (progn
+        (byte-compile-warn-wrong-args form 3)
+        (byte-compile-normal-call
+         `(signal 'wrong-number-of-arguments '(,(car form)
+                                               ,(length (cdr form))))))
+    (byte-compile-form (nth 1 form))
+    (byte-compile-form (nth 2 form))
+    (byte-compile-out 'byte-bind-multiple-value-limits 0)
+    (byte-compile-form (nth 3 form))
+    (byte-compile-out (get (car form) 'byte-opcode) 0)
+    (pushnew '(subrp (symbol-function 'multiple-value-call))
+             byte-compile-checks-on-load
+             :test #'equal)))
+
+(defun byte-compile-throw (form)
+  ;; We can't use byte-compile-two-args for throw because in the event that
+  ;; the form does not have two args, it tries to #'funcall it expecting a
+  ;; runtime wrong-number-of-arguments error. Now that #'throw is a special
+  ;; form, it provokes an invalid-function error instead (or at least it
+  ;; should; there's a kludge around for the moment in eval.c that avoids
+  ;; that, but this file should not assume that that will always be there).
+  (if (/= 2 (length (cdr form)))
+      (progn
+        (byte-compile-warn-wrong-args form 2)
+        (byte-compile-normal-call
+         `(signal 'wrong-number-of-arguments '(,(car form)
+                                               ,(length (cdr form))))))
+    (byte-compile-form (nth 1 form))  ;; Push the arguments
+    (byte-compile-form (nth 2 form))
+    (byte-compile-out (get (car form) 'byte-opcode) 0)
+    (pushnew '(null (function-max-args 'throw))
+             byte-compile-checks-on-load
+             :test #'equal)))
 
 ;;; top-level forms elsewhere
 
@@ -4115,6 +4213,8 @@
      ;; This is actually an unnecessary case, because there should be
      ;; no more opcodes behind byte-return.
      (setq byte-compile-depth nil))
+    (byte-multiple-value-call
+     (setq byte-compile-depth (- byte-compile-depth offset)))
     (t
      (setq byte-compile-depth (+ byte-compile-depth
 				 (or (aref byte-stack+-info
--- a/lisp/cl-compat.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/cl-compat.el	Sun Aug 16 20:55:49 2009 +0100
@@ -59,52 +59,10 @@
 (defun keyword-of (sym)
   (or (keywordp sym) (keywordp (intern (format ":%s" sym)))))
 
-
-;;; Multiple values.  Note that the new package uses a different
-;;; convention for multiple values.  The following definitions
-;;; emulate the old convention; all function names have been changed
-;;; by capitalizing the first letter: Values, Multiple-value-*,
-;;; to avoid conflict with the new-style definitions in cl-macs.
-
-(put 'Multiple-value-bind  'lisp-indent-function 2)
-(put 'Multiple-value-setq  'lisp-indent-function 2)
-(put 'Multiple-value-call  'lisp-indent-function 1)
-(put 'Multiple-value-prog1 'lisp-indent-function 1)
-
-(defvar *mvalues-values* nil)
-
-(defun Values (&rest val-forms)
-  (setq *mvalues-values* val-forms)
-  (car val-forms))
-
-(defun Values-list (val-forms)
-  (apply 'values val-forms))
-
-(defmacro Multiple-value-list (form)
-  (list 'let* (list '(*mvalues-values* nil) (list '*mvalues-temp* form))
-	'(or (and (eq *mvalues-temp* (car *mvalues-values*)) *mvalues-values*)
-	     (list *mvalues-temp*))))
-
-(defmacro Multiple-value-call (function &rest args)
-  (list 'apply function
-	(cons 'append
-	      (mapcar (function (lambda (x) (list 'Multiple-value-list x)))
-		      args))))
-
-(defmacro Multiple-value-bind (vars form &rest body)
-  (list* 'multiple-value-bind vars (list 'Multiple-value-list form) body))
-
-(defmacro Multiple-value-setq (vars form)
-  (list 'multiple-value-setq vars (list 'Multiple-value-list form)))
-
-(defmacro Multiple-value-prog1 (form &rest body)
-  (list 'prog1 form (list* 'let '((*mvalues-values* nil)) body)))
-
-
 ;;; Routines for parsing keyword arguments.
 
 (defun build-klist (arglist keys &optional allow-others)
-  (let ((res (Multiple-value-call 'mapcar* 'cons (unzip-lists arglist))))
+  (let ((res (multiple-value-call 'mapcar* 'cons (unzip-lists arglist))))
     (or allow-others
 	(let ((bad (set-difference (mapcar 'car res) keys)))
 	  (if bad (error "Bad keywords: %s not in %s" bad keys))))
@@ -124,25 +82,23 @@
     (if test-not (not (funcall test-not item elt))
       (funcall (or test 'eql) item elt))))
 
-
 ;;; Rounding functions with old-style multiple value returns.
 
-(defun cl-floor (a &optional b) (Values-list (floor* a b)))
-(defun cl-ceiling (a &optional b) (Values-list (ceiling* a b)))
-(defun cl-round (a &optional b) (Values-list (round* a b)))
-(defun cl-truncate (a &optional b) (Values-list (truncate* a b)))
+(defun cl-floor (a &optional b) (values-list (floor* a b)))
+(defun cl-ceiling (a &optional b) (values-list (ceiling* a b)))
+(defun cl-round (a &optional b) (values-list (round* a b)))
+(defun cl-truncate (a &optional b) (values-list (truncate* a b)))
 
 (defun safe-idiv (a b)
   (let* ((q (/ (abs a) (abs b)))
          (s (* (signum a) (signum b))))
-    (Values q (- a (* s q b)) s)))
-
+    (values q (- a (* s q b)) s)))
 
 ;; Internal routines.
 
 (defun pair-with-newsyms (oldforms)
   (let ((newsyms (mapcar (function (lambda (x) (gensym))) oldforms)))
-    (Values (mapcar* 'list newsyms oldforms) newsyms)))
+    (values (mapcar* 'list newsyms oldforms) newsyms)))
 
 (defun zip-lists (evens odds)
   (mapcan 'list evens odds))
@@ -151,7 +107,7 @@
   (let ((e nil) (o nil))
     (while list
       (setq e (cons (car list) e) o (cons (cadr list) o) list (cddr list)))
-    (Values (nreverse e) (nreverse o))))
+    (values (nreverse e) (nreverse o))))
 
 (defun reassemble-argslists (list)
   (let ((n (apply 'min (mapcar 'length list))) (res nil))
--- a/lisp/cl-macs.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/cl-macs.el	Sun Aug 16 20:55:49 2009 +0100
@@ -715,24 +715,30 @@
 
 (defvar cl-active-block-names nil)
 
-(put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block)
-(defun cl-byte-compile-block (cl-form)
-  (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 'cl-byte-compile-throw)
-(defun cl-byte-compile-throw (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-normal-call (cons 'throw (cdr cl-form))))
+(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)))))
 
 ;;;###autoload
 (defmacro return (&optional result)
@@ -1841,47 +1847,70 @@
 	      (list 'function (cons 'lambda rest)))
 	(list 'quote func)))
 
-
-;;; Multiple values.
+;;; Multiple values. We support full Common Lisp conventions here.
 
 ;;;###autoload
-(defmacro multiple-value-bind (vars form &rest body)
-  "(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values.
-FORM must return a list; the BODY is then executed with the first N elements
-of this list bound (`let'-style) to each of the symbols SYM in turn.  This
-is analogous to the Common Lisp `multiple-value-bind' macro, using lists to
-simulate true multiple return values.  For compatibility, (values A B C) is
-a synonym for (list A B C)."
-  (let ((temp (gensym)) (n -1))
-    (list* 'let* (cons (list temp form)
-		       (mapcar #'(lambda (v)
-				   (list v (list 'nth (setq n (1+ n)) temp)))
-			       vars))
-	   body)))
+(defmacro multiple-value-bind (syms form &rest body)
+  "Collect and bind multiple return values.
+
+If FORM returns multiple values, each symbol in SYMS is bound to one of
+them, in order, and BODY is executed.  If FORM returns fewer multiple values
+than there are SYMS, remaining SYMS are bound to nil.  If FORM does
+not return multiple values, it is treated as returning one multiple value.
+
+Returns the value given by the last element of BODY."
+  (if (null syms)
+      `(progn ,form ,@body)
+    (if (= 1 (length syms))
+        ;; Code written to deal with other "implementations" of multiple
+        ;; values may have a one-element SYMS.
+        `(let ((,(car syms) ,form))
+          ,@body)
+      (let ((temp (gensym)))
+        `(let* ((,temp (multiple-value-list-internal 0 ,(length syms) ,form))
+                ,@(loop 
+                    for var in syms
+                    collect `(,var (prog1 (car ,temp)
+                                     (setq ,temp (cdr ,temp))))))
+          ,@body)))))
 
 ;;;###autoload
-(defmacro multiple-value-setq (vars form)
-  "(multiple-value-setq (SYM SYM...) FORM): collect multiple return values.
-FORM must return a list; the first N elements of this list are stored in
-each of the symbols SYM in turn.  This is analogous to the Common Lisp
-`multiple-value-setq' macro, using lists to simulate true multiple return
-values.  For compatibility, (values A B C) is a synonym for (list A B C)."
-  (cond ((null vars) (list 'progn form nil))
-	((null (cdr vars)) (list 'setq (car vars) (list 'car form)))
-	(t
-	 (let* ((temp (gensym)) (n 0))
-	   (list 'let (list (list temp form))
-		 (list 'prog1 (list 'setq (pop vars) (list 'car temp))
-		       (cons 'setq
-			     (apply 'nconc
-				    (mapcar
-				     #'(lambda (v)
-					 (list v (list
-						  'nth
-						  (setq n (1+ n))
-						  temp)))
-					    vars)))))))))
-
+(defmacro multiple-value-setq (syms form)
+  "Collect and set multiple values.
+
+FORM should normally return multiple values; the first N values are stored
+in the symbols in SYMS in turn.  If FORM returns fewer than N values, the
+remaining symbols have their values set to nil.  FORM not returning multiple
+values is treated as FORM returning one multiple value, with other elements
+of SYMS initialized to nil.
+
+Returns the first of the multiple values given by FORM."
+  (if (null syms)
+      ;; Never return multiple values from multiple-value-setq:
+      (and form `(values ,form))
+    (if (= 1 (length syms))
+        `(setq ,(car syms) ,form)
+      (let ((temp (gensym)))
+        `(let* ((,temp (multiple-value-list-internal 0 ,(length syms) ,form)))
+           (setq ,@(loop
+                     for sym in syms
+                     nconc `(,sym (car-safe ,temp)
+                             ,temp (cdr-safe ,temp))))
+           ,(car syms))))))
+
+;;;###autoload
+(defmacro multiple-value-list (form)
+  "Evaluate FORM and return a list of the multiple values it returned."
+  `(multiple-value-list-internal 0 multiple-values-limit ,form))
+
+;;;###autoload
+(defmacro nth-value (n form)
+  "Evaluate FORM and return the Nth multiple value it returned."
+  (if (integerp n)
+      `(car (multiple-value-list-internal ,n ,(1+ n) ,form))
+    (let ((temp (gensym)))
+      `(let ((,temp ,n))
+        (car (multiple-value-list-internal ,temp (1+ ,temp) ,form))))))
 
 ;;; Declarations.
 
@@ -2346,8 +2375,9 @@
 	(store-temp (gensym "--values-store--")))
     (list (apply 'append (mapcar 'first methods))
 	  (apply 'append (mapcar 'second methods))
-	  (list store-temp)
-	  (cons 'list
+	  `((,store-temp
+	     (multiple-value-list-internal 0 ,(if args (length args) 1))))
+	  (cons 'values
 		(mapcar #'(lambda (m)
 			    (cl-setf-do-store (cons (car (third m)) (fourth m))
 					      (list 'pop store-temp)))
@@ -2410,11 +2440,25 @@
 (defun cl-setf-do-store (spec val)
   (let ((sym (car spec))
 	(form (cdr spec)))
-    (if (or (cl-const-expr-p val)
-	    (and (cl-simple-expr-p val) (eq (cl-expr-contains form sym) 1))
-	    (cl-setf-simple-store-p sym form))
-	(subst val sym form)
-      (list 'let (list (list sym val)) form))))
+    (if (consp sym)
+	;; XEmacs change, only used for implementing #'values at the moment.
+	(let* ((orig (copy-list sym))
+	       (intermediate (last orig))
+	       (circular-limit 32))
+	  (while (consp (car intermediate))
+	    (when (zerop circular-limit)
+	      (error 'circular-list "Form seems to contain loops"))
+	    (setq intermediate (last (car intermediate))
+		  circular-limit (1- circular-limit)))
+	  (setcdr intermediate (list val))
+	  `(let (,orig)
+	    ,form))
+      (if (or (cl-const-expr-p val)
+	      (and (cl-simple-expr-p val)
+		   (eq (cl-expr-contains form sym) 1))
+	      (cl-setf-simple-store-p sym form))
+	  (subst val sym form)
+	(list 'let (list (list sym val)) form)))))
 
 (defun cl-setf-simple-store-p (sym form)
   (and (consp form) (eq (cl-expr-contains form sym) 1)
--- a/lisp/cl.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/cl.el	Sun Aug 16 20:55:49 2009 +0100
@@ -209,48 +209,24 @@
 
 ;;; Blocks and exits.
 
-(defalias 'cl-block-wrapper 'identity)
+;; 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)
 
-
-;;; Multiple values.  True multiple values are not supported, or even
-;;; simulated.  Instead, multiple-value-bind and friends simply expect
-;;; the target form to return the values as a list.
-
-(defsubst values (&rest values)
-  "Return multiple values, Common Lisp style.
-The arguments of `values' are the values
-that the containing function should return."
-  values)
-
-(defsubst values-list (list)
-  "Return multiple values, Common Lisp style, taken from a list.
-LIST specifies the list of values
-that the containing function should return."
-  list)
+;;; XEmacs; multiple values are in eval.c and cl-macs.el. 
 
-(defsubst multiple-value-list (expression)
-  "Return a list of the multiple values produced by EXPRESSION.
-This handles multiple values in Common Lisp style, but it does not
-work right when EXPRESSION calls an ordinary Emacs Lisp function
-that returns just one value."
-  expression)
+;;; We no longer support `multiple-value-apply', which was ill-conceived to
+;;; start with, is not specified by Common Lisp, and which nothing uses,
+;;; according to Google Code Search, as of Sat Mar 14 23:31:35 GMT 2009. 
 
-(defsubst multiple-value-apply (function expression)
-  "Evaluate EXPRESSION to get multiple values and apply FUNCTION to them.
-This handles multiple values in Common Lisp style, but it does not work
-right when EXPRESSION calls an ordinary Emacs Lisp function that returns just
-one value."
-  (apply function expression))
-
-(defalias 'multiple-value-call 'apply)  ; only works for one arg
-
-(defsubst nth-value (n expression)
-  "Evaluate EXPRESSION to get multiple values and return the Nth one.
-This handles multiple values in Common Lisp style, but it does not work
-right when EXPRESSION calls an ordinary Emacs Lisp function that returns just
-one value."
-  (nth n expression))
+(make-obsolete 'multiple-value-apply 'multiple-value-call)
 
 ;;; Macros.
 
--- a/lisp/lisp-mode.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/lisp-mode.el	Sun Aug 16 20:55:49 2009 +0100
@@ -424,36 +424,55 @@
 been treated noninteractively.
 
 The printed messages are \"defvar treated as defconst\" and \"defcustom
- evaluation forced\".  See `eval-interactive' for more details."
+evaluation forced\".  See `eval-interactive' for more details."
   :type 'boolean
   :group 'lisp)
 
 (defun eval-interactive (expr)
-  "Like `eval' except that it transforms defvars to defconsts.
-The evaluation of defcustom forms is forced."
+  "Evaluate EXPR; pass back multiple values, transform defvars to defconsts. 
+
+Always returns a list.  The length of this list will be something other than
+one if the form returned multiple values.  It will be zero if the form
+returned a single zero-length multiple value."
   (cond ((and (eq (car-safe expr) 'defvar)
 	      (> (length expr) 2))
-	 (eval (cons 'defconst (cdr expr)))
+	 (setq expr (multiple-value-list (eval (cons 'defconst (cdr expr)))))
 	 (when eval-interactive-verbose
 	   (message "defvar treated as defconst")
 	   (sit-for 1)
 	   (message ""))
-	 (nth 1 expr))
+         expr)
 	((and (eq (car-safe expr) 'defcustom)
 	      (> (length expr) 2)
 	      (default-boundp (nth 1 expr)))
 	 ;; Force variable to be bound
-	 ;; #### defcustom might specify a different :set method.
-	 (set-default (nth 1 expr) (eval (nth 2 expr)))
+         (funcall 
+          (or (plist-get expr :set) #'custom-set-default)
+          (nth 1 expr) (eval (nth 2 expr)))
 	 ;; And evaluate the defcustom
-	 (eval expr)
+	 (setq expr (multiple-value-list (eval expr)))
 	 (when eval-interactive-verbose
 	   (message "defcustom evaluation forced")
 	   (sit-for 1)
 	   (message ""))
-	 (nth 1 expr))
+         expr)
 	(t
-	 (eval expr))))
+	 (multiple-value-list (eval expr)))))
+
+(defun prin1-list-as-multiple-values (multiple-value-list &optional stream)
+  "Call `prin1' on each element of MULTIPLE-VALUE-LIST, separated by \" ;\\n\"
+
+If MULTIPLE-VALUE-LIST is zero-length, print the text
+\"#<zero length multiple value> ;\\n\".  Always returns nil."
+  (loop for value in multiple-value-list
+    with seen-first = nil
+    do
+    (if seen-first
+        (princ " ;\n" stream)
+      (setq seen-first t))
+    (prin1 value stream)
+    finally (unless seen-first
+	      (princ "#<zero length multiple value> ;" stream))))
 
 ;; XEmacs change, based on Bob Weiner suggestion
 (defun eval-last-sexp (eval-last-sexp-arg-internal) ;dynamic scoping wonderment
@@ -463,31 +482,32 @@
   (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))
 	(opoint (point))
 	ignore-quotes)
-    (prin1 (eval-interactive
-	    (letf (((syntax-table) emacs-lisp-mode-syntax-table))
-	      (save-excursion
-		;; If this sexp appears to be enclosed in `...' then
-		;; ignore the surrounding quotes.
-		(setq ignore-quotes (or (eq (char-after) ?\')
-					(eq (char-before) ?\')))
-		(forward-sexp -1)
-		;; vladimir@cs.ualberta.ca 30-Jul-1997: skip ` in
-		;; `variable' so that the value is returned, not the
-		;; name.
-		(if (and ignore-quotes
-			 (eq (char-after) ?\`))
-		    (forward-char))
-		(save-restriction
-		  (narrow-to-region (point-min) opoint)
-		  (let ((expr (read (current-buffer))))
-		    (if (eq (car-safe expr) 'interactive)
-			;; If it's an (interactive ...) form, it's
-			;; more useful to show how an interactive call
-			;; would use it.
-			`(call-interactively
-			  (lambda (&rest args)
-			    ,expr args))
-		      expr)))))))))
+    (prin1-list-as-multiple-values
+     (eval-interactive
+      (letf (((syntax-table) emacs-lisp-mode-syntax-table))
+        (save-excursion
+          ;; If this sexp appears to be enclosed in `...' then
+          ;; ignore the surrounding quotes.
+          (setq ignore-quotes (or (eq (char-after) ?\')
+                                  (eq (char-before) ?\')))
+          (forward-sexp -1)
+          ;; vladimir@cs.ualberta.ca 30-Jul-1997: skip ` in
+          ;; `variable' so that the value is returned, not the
+          ;; name.
+          (if (and ignore-quotes
+                   (eq (char-after) ?\`))
+              (forward-char))
+          (save-restriction
+            (narrow-to-region (point-min) opoint)
+            (let ((expr (read (current-buffer))))
+              (if (eq (car-safe expr) 'interactive)
+                  ;; If it's an (interactive ...) form, it's
+                  ;; more useful to show how an interactive call
+                  ;; would use it.
+                  `(call-interactively
+                    (lambda (&rest args)
+                      ,expr args))
+                expr)))))))))
 
 (defun eval-defun (eval-defun-arg-internal)
   "Evaluate defun that point is in or before.
@@ -495,11 +515,12 @@
 With argument, insert value in current buffer after the defun."
   (interactive "P")
   (let ((standard-output (if eval-defun-arg-internal (current-buffer) t)))
-    (prin1 (eval-interactive (save-excursion
-			       (end-of-defun)
-			       (beginning-of-defun)
-			       (read (current-buffer)))))))
-
+    (prin1-list-as-multiple-values
+     (eval-interactive
+      (save-excursion
+        (end-of-defun)
+        (beginning-of-defun)
+        (read (current-buffer)))))))
 
 (defun lisp-comment-indent ()
   (if (looking-at "\\s<\\s<\\s<")
--- a/lisp/mouse.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/mouse.el	Sun Aug 16 20:55:49 2009 +0100
@@ -278,18 +278,23 @@
 	     (message "Regex \"%s\" not found" exp)
 	     (ding nil 'quiet)))
 	  (t (setq val (if (fboundp 'eval-interactive)
-			   (eval-interactive exp)
-			 (eval exp)))))
-    (setq result-str (prin1-to-string val))
+                           (eval-interactive exp)
+			 (list (eval exp))))))
+    (setq result-str (mapconcat #'prin1-to-string val " ;\n"))
     ;; #### -- need better test
     (if (and (not force-window)
-	     (<= (length result-str) (window-width (selected-window))))
+	     (<= (length result-str) (window-width (selected-window)))
+             (not (string-match "\n" result-str)))
 	(message "%s" result-str)
       (with-output-to-temp-buffer "*Mouse-Eval*"
-	(if-fboundp 'pprint
-	    (pprint val)
-	  (prin1 val)))
-      )))
+        (loop
+          for value in val 
+          with seen-first = nil
+          do
+          (if seen-first 
+              (princ " ;\n")
+            (setq seen-first t))
+          (cl-prettyprint value))))))
 
 (defun mouse-line-length (event)
   "Print the length of the line indicated by the pointer."
--- a/lisp/obsolete.el	Sun Aug 16 14:58:57 2009 +0100
+++ b/lisp/obsolete.el	Sun Aug 16 20:55:49 2009 +0100
@@ -395,5 +395,18 @@
 
 (make-obsolete 'function-called-at-point 'function-at-point)
 
+;; As of 21.5, #'throw is a special form. This makes bytecode using it
+;; compiled for 21.4 fail; making this function available works around that.
+(defun obsolete-throw (tag value)
+  "Ugly compatibility hack.
+
+See the implementation of #'funcall in eval.c.  This should be removed once
+we no longer encounter bytecode from 21.4."
+  (throw tag value))
+
+(make-obsolete
+ 'obsolete-throw
+ "it says `obsolete' in the name, you know you shouldn't be using this.")
+
 (provide 'obsolete)
 ;;; obsolete.el ends here
--- a/man/ChangeLog	Sun Aug 16 14:58:57 2009 +0100
+++ b/man/ChangeLog	Sun Aug 16 20:55:49 2009 +0100
@@ -1,3 +1,8 @@
+2009-08-11  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cl.texi (Organization): 
+	Remove references to the obsolete multiple-value emulating code.
+
 2009-07-28  Stephen Turnbull  <stephen@xemacs.org>
 
 	* internals/internals.texi (Redisplay Piece by Piece):
--- a/man/cl.texi	Sun Aug 16 14:58:57 2009 +0100
+++ b/man/cl.texi	Sun Aug 16 20:55:49 2009 +0100
@@ -249,9 +249,8 @@
 There is another file, @file{cl-compat.el}, which defines some
 routines from the older @file{cl.el} package that are no longer
 present in the new package.  This includes internal routines
-like @code{setelt} and @code{zip-lists}, deprecated features
-like @code{defkeyword}, and an emulation of the old-style
-multiple-values feature.  @xref{Old CL Compatibility}.
+like @code{setelt} and @code{zip-lists}, and deprecated features
+like @code{defkeyword}.  @xref{Old CL Compatibility}.
 
 @node Installation, Naming Conventions, Organization, Overview
 @section Installation
@@ -5345,14 +5344,6 @@
 The @code{loop} macro is complete except that @code{loop-finish}
 and type specifiers are unimplemented.
 
-The multiple-value return facility treats lists as multiple
-values, since Emacs Lisp cannot support multiple return values
-directly.  The macros will be compatible with Common Lisp if
-@code{values} or @code{values-list} is always used to return to
-a @code{multiple-value-bind} or other multiple-value receiver;
-if @code{values} is used without @code{multiple-value-@dots{}}
-or vice-versa the effect will be different from Common Lisp.
-
 Many Common Lisp declarations are ignored, and others match
 the Common Lisp standard in concept but not in detail.  For
 example, local @code{special} declarations, which are purely
@@ -5377,14 +5368,6 @@
 Following is a list of all known incompatibilities between this package
 and the older Quiroz @file{cl.el} package.
 
-This package's emulation of multiple return values in functions is
-incompatible with that of the older package.  That package attempted
-to come as close as possible to true Common Lisp multiple return
-values; unfortunately, it could not be 100% reliable and so was prone
-to occasional surprises if used freely.  This package uses a simpler
-method, namely replacing multiple values with lists of values, which
-is more predictable though more noticeably different from Common Lisp.
-
 The @code{defkeyword} form and @code{keywordp} function are not
 implemented in this package.
 
@@ -5449,19 +5432,6 @@
 use the more natural keyword argument processing offered by
 @code{defun*}.
 
-Multiple return values are treated differently by the two
-Common Lisp packages.  The old package's method was more
-compatible with true Common Lisp, though it used heuristics
-that caused it to report spurious multiple return values in
-certain cases.  The @code{cl-compat} package defines a set
-of multiple-value macros that are compatible with the old
-CL package; again, they are heuristic in nature, but they
-are guaranteed to work in any case where the old package's
-macros worked.  To avoid name collision with the ``official''
-multiple-value facilities, the ones in @code{cl-compat} have
-capitalized names:  @code{Values}, @code{Values-list},
-@code{Multiple-value-bind}, etc.
-
 The functions @code{cl-floor}, @code{cl-ceiling}, @code{cl-truncate},
 and @code{cl-round} are defined by @code{cl-compat} to use the
 old-style multiple-value mechanism, just as they did in the old
--- a/src/ChangeLog	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/ChangeLog	Sun Aug 16 20:55:49 2009 +0100
@@ -1,3 +1,118 @@
+2009-08-11  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* bytecode.c (enum Opcode /* Byte codes */): 
+	Add four new bytecodes, to deal with multiple values. 
+	(POP_WITH_MULTIPLE_VALUES): New macro. 
+	(POP): Modify this macro to ignore multiple values. 
+	(DISCARD_PRESERVING_MULTIPLE_VALUES): New macro. 
+	(DISCARD): Modify this macro to ignore multiple values. 
+	(TOP_WITH_MULTIPLE_VALUES): New macro. 
+	(TOP_ADDRESS): New macro. 
+	(TOP): Modify this macro to ignore multiple values. 
+	(TOP_LVALUE): New macro.
+	(Bcall): Ignore multiple values where appropriate. 
+	(Breturn): Pass back multiple values.
+	(Bdup): Preserve multiple values.
+	Use TOP_LVALUE with most bytecodes that assign anything to
+	anything. 
+	(Bbind_multiple_value_limits, Bmultiple_value_call,
+	Bmultiple_value_list_internal, Bthrow): Implement the new
+	bytecodes. 
+	(Bgotoifnilelsepop, Bgotoifnonnilelsepop, BRgotoifnilelsepop,
+	BRgotoifnonnilelsepop): 
+	Discard any multiple values.
+	* callint.c (Fcall_interactively):
+	Ignore multiple values when calling #'eval, in two places.
+	* device-x.c (x_IO_error_handler): 
+	* macros.c (pop_kbd_macro_event): 
+	* eval.c (Fsignal): 
+	* eval.c (flagged_a_squirmer): 
+	Call throw_or_bomb_out, not Fthrow, now that the latter is a
+	special form. 
+	* eval.c: 
+	Make Qthrow, Qobsolete_throw available as symbols. 
+	Provide multiple_value_current_limit, multiple-values-limit (the
+	latter as specified by Common Lisp. 
+	* eval.c (For): 
+	Ignore multiple values when comparing with Qnil, but pass any
+	multiple values back for the last arg.
+	* eval.c (Fand): 
+	Ditto.
+	* eval.c (Fif):
+	Ignore multiple values when examining the result of the
+	condition. 
+	* eval.c (Fcond): 
+	Ignore multiple values when comparing what the clauses give, but
+	pass them back if a clause gave non-nil.
+	* eval.c (Fprog2): 
+	Never pass back multiple values.
+	* eval.c (FletX, Flet): 
+	Ignore multiple when evaluating what exactly symbols should be
+	bound to.
+	* eval.c (Fwhile): 
+	Ignore multiple values when evaluating the test.
+	* eval.c (Fsetq, Fdefvar, Fdefconst): 
+	Ignore multiple values.	
+	* eval.c (Fthrow): 
+	Declare this as a special form; ignore multiple values for TAG,
+	preserve them for VALUE.
+	* eval.c (throw_or_bomb_out): 
+	Make this available to other files, now Fthrow is a special form.
+	* eval.c (Feval): 
+	Ignore multiple values when calling a compiled function, a
+	non-special-form subr, or a lambda expression.
+	* eval.c (Ffuncall): 
+	If we attempt to call #'throw (now a special form) as a function,
+	don't error, call #'obsolete-throw instead. 
+	* eval.c (make_multiple_value, multiple_value_aset)
+	(multiple_value_aref, print_multiple_value, mark_multiple_value)
+	(size_multiple_value): 
+	Implement the multiple_value type. Add a long comment describing
+	our implementation.
+	* eval.c (bind_multiple_value_limits): 
+	New function, used by the bytecode and by #'multiple-value-call,
+	#'multiple-value-list-internal. 
+	* eval.c (multiple_value_call): 
+	New function, used by the bytecode and #'multiple-value-call.
+	* eval.c (Fmultiple_value_call): 
+	New special form.
+	* eval.c (multiple_value_list_internal): 
+	New function, used by the byte code and
+	#'multiple-value-list-internal.
+	* eval.c (Fmultiple_value_list_internal, Fmultiple_value_prog1): 
+	New special forms.
+	* eval.c (Fvalues, Fvalues_list): 
+	New Lisp functions.
+	* eval.c (values2): 
+	New function, for C code returning multiple values.
+	* eval.c (syms_of_eval): 
+	Make our new Lisp functions and symbols available.
+	* eval.c (multiple-values-limit): 
+	Make this available to Lisp.
+	* event-msw.c (dde_eval_string): 
+	* event-stream.c (execute_help_form): 
+	* glade.c (connector): 
+	* glyphs-widget.c (glyph_instantiator_to_glyph): 
+	* glyphs.c (evaluate_xpm_color_symbols): 
+	* gui-x.c (wv_set_evalable_slot, button_item_to_widget_value): 
+	* gui.c (gui_item_value, gui_item_display_flush_left): 
+	* lread.c (check_if_suppressed): 
+	* menubar-gtk.c (menu_convert, menu_descriptor_to_widget_1): 
+	* menubar-msw.c (populate_menu_add_item): 
+	* print.c (Fwith_output_to_temp_buffer): 
+	* symbols.c (Fsetq_default): 
+	Ignore multiple values when calling Feval.
+	* symeval.h: 
+	Add the header declarations necessary for the multiple-values
+	implementation. 
+	* inline.c: 
+	#include symeval.h, now that it has some inline functions.
+	* lisp.h: 
+	Update Fthrow's declaration. Make throw_or_bomb_out available to
+	all files. 
+	* lrecord.h (enum lrecord_type): 
+	Add the multiple_value type here. 
+
 2009-07-28  Stephen Turnbull  <stephen@xemacs.org>
 
 	* faces.c (ensure_face_cachel_contains_charset):
--- a/src/bytecode.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/bytecode.c	Sun Aug 16 20:55:49 2009 +0100
@@ -243,6 +243,12 @@
   BlistN 		= 0257,
   BconcatN 		= 0260,
   BinsertN 		= 0261,
+
+  Bbind_multiple_value_limits   = 0262,         /* New in 21.5. */
+  Bmultiple_value_list_internal = 0263,         /* New in 21.5. */
+  Bmultiple_value_call          = 0264,         /* New in 21.5. */
+  Bthrow                        = 0265,         /* New in 21.5. */
+
   Bmember 		= 0266, /* new in v20 */
   Bassq 		= 0267, /* new in v20 */
 
@@ -653,15 +659,44 @@
 /* Push x onto the execution stack. */
 #define PUSH(x) (*++stack_ptr = (x))
 
-/* Pop a value off the execution stack. */
-#define POP (*stack_ptr--)
+/* Pop a value, which may be multiple, off the execution stack. */
+#define POP_WITH_MULTIPLE_VALUES (*stack_ptr--)
+
+/* Pop a value off the execution stack, treating multiple values as single. */
+#define POP (IGNORE_MULTIPLE_VALUES (POP_WITH_MULTIPLE_VALUES))
+
+#define DISCARD_PRESERVING_MULTIPLE_VALUES(n) (stack_ptr -= (n))
 
 /* Discard n values from the execution stack.  */
-#define DISCARD(n) (stack_ptr -= (n))
+#define DISCARD(n) do {                                         \
+    if (1 != multiple_value_current_limit)                      \
+      {                                                         \
+        int i, en = n;                                          \
+        for (i = 0; i < en; i++)                                \
+          {                                                     \
+            *stack_ptr = ignore_multiple_values (*stack_ptr);   \
+            stack_ptr--;                                        \
+          }                                                     \
+      }                                                         \
+    else                                                        \
+      {                                                         \
+        stack_ptr -= (n);                                       \
+      }                                                         \
+  } while (0)
+
+/* Get the value, which may be multiple, at the top of the execution stack;
+   and leave it there. */
+#define TOP_WITH_MULTIPLE_VALUES (*stack_ptr)
+
+#define TOP_ADDRESS (stack_ptr)
 
 /* Get the value which is at the top of the execution stack,
    but don't pop it. */
-#define TOP (*stack_ptr)
+#define TOP (IGNORE_MULTIPLE_VALUES (TOP_WITH_MULTIPLE_VALUES))
+
+#define TOP_LVALUE (*stack_ptr)
+
+
 
 /* See comment before the big switch in execute_optimized_program(). */
 #define GCPRO_STACK  (gcpro1.nvars = stack_ptr - stack_beg)
@@ -859,7 +894,8 @@
 		Fput (TOP, Qbyte_code_meter, make_int (XINT (val) + 1));
 	    }
 #endif
-	  TOP = Ffuncall (n + 1, &TOP);
+          TOP_LVALUE = TOP; /* Ignore multiple values. */
+	  TOP_LVALUE = Ffuncall (n + 1, TOP_ADDRESS);
 	  break;
 
 	case Bunbind:
@@ -895,7 +931,8 @@
 	  break;
 
 	case Bgotoifnilelsepop:
-	  if (NILP (TOP))
+	  /* Discard any multiple value: */
+	  if (NILP (TOP_LVALUE = TOP))
 	    JUMP;
 	  else
 	    {
@@ -905,7 +942,8 @@
 	  break;
 
 	case Bgotoifnonnilelsepop:
-	  if (!NILP (TOP))
+	  /* Discard any multiple value: */
+	  if (!NILP (TOP_LVALUE = TOP))
 	    JUMP;
 	  else
 	    {
@@ -934,7 +972,7 @@
 	  break;
 
 	case BRgotoifnilelsepop:
-	  if (NILP (TOP))
+	  if (NILP (TOP_LVALUE = TOP))
 	    JUMPR;
 	  else
 	    {
@@ -944,7 +982,7 @@
 	  break;
 
 	case BRgotoifnonnilelsepop:
-	  if (!NILP (TOP))
+	  if (!NILP (TOP_LVALUE = TOP))
 	    JUMPR;
 	  else
 	    {
@@ -960,7 +998,7 @@
 	  if (specpdl_depth() != speccount)
 	    invalid_byte_code ("unbalanced specbinding stack", Qunbound);
 #endif
-	  return TOP;
+	  return TOP_WITH_MULTIPLE_VALUES;
 
 	case Bdiscard:
 	  DISCARD (1);
@@ -968,7 +1006,7 @@
 
 	case Bdup:
 	  {
-	    Lisp_Object arg = TOP;
+	    Lisp_Object arg = TOP_WITH_MULTIPLE_VALUES;
 	    PUSH (arg);
 	    break;
 	  }
@@ -978,17 +1016,22 @@
 	  break;
 
 	case Bcar:
-	  /* Fcar can GC via wrong_type_argument. */
-	  /* GCPRO_STACK; */
-	  TOP = CONSP (TOP) ? XCAR (TOP) : Fcar (TOP);
-	  break;
+          {
+            /* Fcar can GC via wrong_type_argument. */
+            /* GCPRO_STACK; */
+            Lisp_Object arg = TOP;
+            TOP_LVALUE = CONSP (arg) ? XCAR (arg) : Fcar (arg);
+            break;
+          }
 
 	case Bcdr:
-	  /* Fcdr can GC via wrong_type_argument. */
-	  /* GCPRO_STACK; */
-	  TOP = CONSP (TOP) ? XCDR (TOP) : Fcdr (TOP);
-	  break;
-
+          {
+            /* Fcdr can GC via wrong_type_argument. */
+            /* GCPRO_STACK; */
+            Lisp_Object arg = TOP;
+            TOP_LVALUE = CONSP (arg) ? XCDR (arg) : Fcdr (arg);
+            break;
+          }
 
 	case Bunbind_all:
 	  /* To unbind back to the beginning of this frame.  Not used yet,
@@ -1001,62 +1044,62 @@
 	    Lisp_Object arg = POP;
 	    /* Fcar and Fnthcdr can GC via wrong_type_argument. */
 	    /* GCPRO_STACK; */
-	    TOP = Fcar (Fnthcdr (TOP, arg));
+	    TOP_LVALUE = Fcar (Fnthcdr (TOP, arg));
 	    break;
 	  }
 
 	case Bsymbolp:
-	  TOP = SYMBOLP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = SYMBOLP (TOP) ? Qt : Qnil;
 	  break;
 
 	case Bconsp:
-	  TOP = CONSP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = CONSP (TOP) ? Qt : Qnil;
 	  break;
 
 	case Bstringp:
-	  TOP = STRINGP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = STRINGP (TOP) ? Qt : Qnil;
 	  break;
 
 	case Blistp:
-	  TOP = LISTP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = LISTP (TOP) ? Qt : Qnil;
 	  break;
 
 	case Bnumberp:
 #ifdef WITH_NUMBER_TYPES
-	  TOP = NUMBERP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = NUMBERP (TOP) ? Qt : Qnil;
 #else
-	  TOP = INT_OR_FLOATP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = INT_OR_FLOATP (TOP) ? Qt : Qnil;
 #endif
 	  break;
 
 	case Bintegerp:
 #ifdef HAVE_BIGNUM
-	  TOP = INTEGERP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = INTEGERP (TOP) ? Qt : Qnil;
 #else
-	  TOP = INTP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = INTP (TOP) ? Qt : Qnil;
 #endif
 	  break;
 
 	case Beq:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = EQ_WITH_EBOLA_NOTICE (TOP, arg) ? Qt : Qnil;
+	    TOP_LVALUE = EQ_WITH_EBOLA_NOTICE (TOP, arg) ? Qt : Qnil;
 	    break;
 	  }
 
 	case Bnot:
-	  TOP = NILP (TOP) ? Qt : Qnil;
+	  TOP_LVALUE = NILP (TOP) ? Qt : Qnil;
 	  break;
 
 	case Bcons:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fcons (TOP, arg);
+	    TOP_LVALUE = Fcons (TOP, arg);
 	    break;
 	  }
 
 	case Blist1:
-	  TOP = Fcons (TOP, Qnil);
+	  TOP_LVALUE = Fcons (TOP, Qnil);
 	  break;
 
 
@@ -1079,7 +1122,7 @@
 		DISCARD (1);
 		goto list_loop;
 	      }
-	    TOP = list;
+	    TOP_LVALUE = list;
 	    break;
 	  }
 
@@ -1097,101 +1140,107 @@
 	  DISCARD (n - 1);
 	  /* Apparently `concat' can GC; Fconcat GCPROs its arguments. */
 	  /* GCPRO_STACK; */
-	  TOP = Fconcat (n, &TOP);
+          TOP_LVALUE = TOP; /* Ignore multiple values. */
+	  TOP_LVALUE = Fconcat (n, TOP_ADDRESS);
 	  break;
 
 
 	case Blength:
-	  TOP = Flength (TOP);
+	  TOP_LVALUE = Flength (TOP);
 	  break;
 
 	case Baset:
 	  {
 	    Lisp_Object arg2 = POP;
 	    Lisp_Object arg1 = POP;
-	    TOP = Faset (TOP, arg1, arg2);
+	    TOP_LVALUE = Faset (TOP, arg1, arg2);
 	    break;
 	  }
 
 	case Bsymbol_value:
 	  /* Why does this need GCPRO_STACK?  If not, remove others, too. */
 	  /* GCPRO_STACK; */
-	  TOP = Fsymbol_value (TOP);
+	  TOP_LVALUE = Fsymbol_value (TOP);
 	  break;
 
 	case Bsymbol_function:
-	  TOP = Fsymbol_function (TOP);
+	  TOP_LVALUE = Fsymbol_function (TOP);
 	  break;
 
 	case Bget:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fget (TOP, arg, Qnil);
+	    TOP_LVALUE = Fget (TOP, arg, Qnil);
 	    break;
 	  }
 
 	case Bsub1:
+          {
 #ifdef HAVE_BIGNUM
-	  TOP = Fsub1 (TOP);
+            TOP_LVALUE = Fsub1 (TOP);
 #else
-	  TOP = INTP (TOP) ? INT_MINUS1 (TOP) : Fsub1 (TOP);
+            Lisp_Object arg = TOP;
+            TOP_LVALUE = INTP (arg) ? INT_MINUS1 (arg) : Fsub1 (arg);
 #endif
 	  break;
-
+          }
 	case Badd1:
+          {
 #ifdef HAVE_BIGNUM
-	  TOP = Fadd1 (TOP);
+            TOP_LVALUE = Fadd1 (TOP);
 #else
-	  TOP = INTP (TOP) ? INT_PLUS1 (TOP) : Fadd1 (TOP);
+            Lisp_Object arg = TOP;
+            TOP_LVALUE = INTP (arg) ? INT_PLUS1 (arg) : Fadd1 (arg);
 #endif
 	  break;
-
+          }
 
 	case Beqlsign:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = bytecode_arithcompare (TOP, arg) == 0 ? Qt : Qnil;
+	    TOP_LVALUE = bytecode_arithcompare (TOP, arg) == 0 ? Qt : Qnil;
 	    break;
 	  }
 
 	case Bgtr:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = bytecode_arithcompare (TOP, arg) > 0 ? Qt : Qnil;
+	    TOP_LVALUE = bytecode_arithcompare (TOP, arg) > 0 ? Qt : Qnil;
 	    break;
 	  }
 
 	case Blss:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = bytecode_arithcompare (TOP, arg) < 0 ? Qt : Qnil;
+	    TOP_LVALUE = bytecode_arithcompare (TOP, arg) < 0 ? Qt : Qnil;
 	    break;
 	  }
 
 	case Bleq:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = bytecode_arithcompare (TOP, arg) <= 0 ? Qt : Qnil;
+	    TOP_LVALUE = bytecode_arithcompare (TOP, arg) <= 0 ? Qt : Qnil;
 	    break;
 	  }
 
 	case Bgeq:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = bytecode_arithcompare (TOP, arg) >= 0 ? Qt : Qnil;
+	    TOP_LVALUE = bytecode_arithcompare (TOP, arg) >= 0 ? Qt : Qnil;
 	    break;
 	  }
 
 
 	case Bnegate:
-	  TOP = bytecode_negate (TOP);
+	  TOP_LVALUE = bytecode_negate (TOP);
 	  break;
 
 	case Bnconc:
 	  DISCARD (1);
 	  /* nconc2 GCPROs before calling this. */
 	  /* GCPRO_STACK; */
-	  TOP = bytecode_nconc2 (&TOP);
+          TOP_LVALUE = TOP; /* Ignore multiple values. */
+	  TOP_LVALUE = bytecode_nconc2 (TOP_ADDRESS);
 	  break;
 
 	case Bplus:
@@ -1199,9 +1248,9 @@
 	    Lisp_Object arg2 = POP;
 	    Lisp_Object arg1 = TOP;
 #ifdef HAVE_BIGNUM
-	    TOP = bytecode_arithop (arg1, arg2, opcode);
+	    TOP_LVALUE = bytecode_arithop (arg1, arg2, opcode);
 #else
-	    TOP = INTP (arg1) && INTP (arg2) ?
+	    TOP_LVALUE = INTP (arg1) && INTP (arg2) ?
 	      INT_PLUS (arg1, arg2) :
 	      bytecode_arithop (arg1, arg2, opcode);
 #endif
@@ -1213,9 +1262,9 @@
 	    Lisp_Object arg2 = POP;
 	    Lisp_Object arg1 = TOP;
 #ifdef HAVE_BIGNUM
-	    TOP = bytecode_arithop (arg1, arg2, opcode);
+	    TOP_LVALUE = bytecode_arithop (arg1, arg2, opcode);
 #else
-	    TOP = INTP (arg1) && INTP (arg2) ?
+	    TOP_LVALUE = INTP (arg1) && INTP (arg2) ?
 	      INT_MINUS (arg1, arg2) :
 	      bytecode_arithop (arg1, arg2, opcode);
 #endif
@@ -1228,7 +1277,7 @@
 	case Bmin:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = bytecode_arithop (TOP, arg, opcode);
+	    TOP_LVALUE = bytecode_arithop (TOP, arg, opcode);
 	    break;
 	  }
 
@@ -1239,7 +1288,8 @@
 	case Binsert:
 	  /* Says it can GC. */
 	  /* GCPRO_STACK; */
-	  TOP = Finsert (1, &TOP);
+          TOP_LVALUE = TOP; /* Ignore multiple values. */
+	  TOP_LVALUE = Finsert (1, TOP_ADDRESS);
 	  break;
 
 	case BinsertN:
@@ -1247,20 +1297,21 @@
 	  DISCARD (n - 1);
 	  /* See Binsert. */
 	  /* GCPRO_STACK; */
-	  TOP = Finsert (n, &TOP);
+          TOP_LVALUE = TOP; /* Ignore multiple values. */
+	  TOP_LVALUE = Finsert (n, TOP_ADDRESS);
 	  break;
 
 	case Baref:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Faref (TOP, arg);
+	    TOP_LVALUE = Faref (TOP, arg);
 	    break;
 	  }
 
 	case Bmemq:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fmemq (TOP, arg);
+	    TOP_LVALUE = Fmemq (TOP, arg);
 	    break;
 	  }
 
@@ -1269,7 +1320,7 @@
 	    Lisp_Object arg = POP;
 	    /* Fset may call magic handlers */
 	    /* GCPRO_STACK; */
-	    TOP = Fset (TOP, arg);
+	    TOP_LVALUE = Fset (TOP, arg);
 	    break;
 	  }
 
@@ -1278,21 +1329,21 @@
 	    Lisp_Object arg = POP;
 	    /* Can QUIT, so can GC, right? */
 	    /* GCPRO_STACK; */
-	    TOP = Fequal (TOP, arg);
+	    TOP_LVALUE = Fequal (TOP, arg);
 	    break;
 	  }
 
 	case Bnthcdr:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fnthcdr (TOP, arg);
+	    TOP_LVALUE = Fnthcdr (TOP, arg);
 	    break;
 	  }
 
 	case Belt:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Felt (TOP, arg);
+	    TOP_LVALUE = Felt (TOP, arg);
 	    break;
 	  }
 
@@ -1301,12 +1352,12 @@
 	    Lisp_Object arg = POP;
 	    /* Can QUIT, so can GC, right? */
 	    /* GCPRO_STACK; */
-	    TOP = Fmember (TOP, arg);
+	    TOP_LVALUE = Fmember (TOP, arg);
 	    break;
 	  }
 
 	case Bgoto_char:
-	  TOP = Fgoto_char (TOP, Qnil);
+	  TOP_LVALUE = Fgoto_char (TOP, Qnil);
 	  break;
 
 	case Bcurrent_buffer:
@@ -1321,7 +1372,7 @@
 	  /* #### WAG: set-buffer may cause Fset's of buffer locals
 	     Didn't prevent crash. :-( */
 	  /* GCPRO_STACK; */
-	  TOP = Fset_buffer (TOP);
+	  TOP_LVALUE = Fset_buffer (TOP);
 	  break;
 
 	case Bpoint_max:
@@ -1337,41 +1388,41 @@
 	    Lisp_Object arg = POP;
 	    /* Can QUIT, so can GC, right? */
 	    /* GCPRO_STACK; */
-	    TOP = Fskip_chars_forward (TOP, arg, Qnil);
+	    TOP_LVALUE = Fskip_chars_forward (TOP, arg, Qnil);
 	    break;
 	  }
 
 	case Bassq:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fassq (TOP, arg);
+	    TOP_LVALUE = Fassq (TOP, arg);
 	    break;
 	  }
 
 	case Bsetcar:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fsetcar (TOP, arg);
+	    TOP_LVALUE = Fsetcar (TOP, arg);
 	    break;
 	  }
 
 	case Bsetcdr:
 	  {
 	    Lisp_Object arg = POP;
-	    TOP = Fsetcdr (TOP, arg);
+	    TOP_LVALUE = Fsetcdr (TOP, arg);
 	    break;
 	  }
 
 	case Bnreverse:
-	  TOP = bytecode_nreverse (TOP);
+	  TOP_LVALUE = bytecode_nreverse (TOP);
 	  break;
 
 	case Bcar_safe:
-	  TOP = CONSP (TOP) ? XCAR (TOP) : Qnil;
+	  TOP_LVALUE = CONSP (TOP) ? XCAR (TOP) : Qnil;
 	  break;
 
 	case Bcdr_safe:
-	  TOP = CONSP (TOP) ? XCDR (TOP) : Qnil;
+	  TOP_LVALUE = CONSP (TOP) ? XCDR (TOP) : Qnil;
 	  break;
 
 	}
@@ -1390,6 +1441,8 @@
 		     const Opbyte *UNUSED (program_ptr),
 		     Opcode opcode)
 {
+  REGISTER int n;
+
   switch (opcode)
     {
 
@@ -1403,7 +1456,7 @@
 	int count = specpdl_depth ();
 	record_unwind_protect (save_window_excursion_unwind,
 			       call1 (Qcurrent_window_configuration, Qnil));
-	TOP = Fprogn (TOP);
+	TOP_LVALUE = Fprogn (TOP);
 	unbind_to (count);
 	break;
       }
@@ -1416,14 +1469,14 @@
     case Bcatch:
       {
 	Lisp_Object arg = POP;
-	TOP = internal_catch (TOP, Feval, arg, 0, 0, 0);
+	TOP_LVALUE = internal_catch (TOP, Feval, arg, 0, 0, 0);
 	break;
       }
 
     case Bskip_chars_backward:
       {
 	Lisp_Object arg = POP;
-	TOP = Fskip_chars_backward (TOP, arg, Qnil);
+	TOP_LVALUE = Fskip_chars_backward (TOP, arg, Qnil);
 	break;
       }
 
@@ -1435,7 +1488,7 @@
       {
 	Lisp_Object arg2 = POP; /* handlers */
 	Lisp_Object arg1 = POP; /* bodyform */
-	TOP = condition_case_3 (arg1, TOP, arg2);
+	TOP_LVALUE = condition_case_3 (arg1, TOP, arg2);
 	break;
       }
 
@@ -1443,51 +1496,51 @@
       {
 	Lisp_Object arg2 = POP;
 	Lisp_Object arg1 = POP;
-	TOP = Fset_marker (TOP, arg1, arg2);
+	TOP_LVALUE = Fset_marker (TOP, arg1, arg2);
 	break;
       }
 
     case Brem:
       {
 	Lisp_Object arg = POP;
-	TOP = Frem (TOP, arg);
+	TOP_LVALUE = Frem (TOP, arg);
 	break;
       }
 
     case Bmatch_beginning:
-      TOP = Fmatch_beginning (TOP);
+      TOP_LVALUE = Fmatch_beginning (TOP);
       break;
 
     case Bmatch_end:
-      TOP = Fmatch_end (TOP);
+      TOP_LVALUE = Fmatch_end (TOP);
       break;
 
     case Bupcase:
-      TOP = Fupcase (TOP, Qnil);
+      TOP_LVALUE = Fupcase (TOP, Qnil);
       break;
 
     case Bdowncase:
-      TOP = Fdowncase (TOP, Qnil);
+      TOP_LVALUE = Fdowncase (TOP, Qnil);
       break;
 
     case Bfset:
       {
 	Lisp_Object arg = POP;
-	TOP = Ffset (TOP, arg);
+	TOP_LVALUE = Ffset (TOP, arg);
 	break;
       }
 
     case Bstring_equal:
       {
 	Lisp_Object arg = POP;
-	TOP = Fstring_equal (TOP, arg);
+	TOP_LVALUE = Fstring_equal (TOP, arg);
 	break;
       }
 
     case Bstring_lessp:
       {
 	Lisp_Object arg = POP;
-	TOP = Fstring_lessp (TOP, arg);
+	TOP_LVALUE = Fstring_lessp (TOP, arg);
 	break;
       }
 
@@ -1495,7 +1548,7 @@
       {
 	Lisp_Object arg2 = POP;
 	Lisp_Object arg1 = POP;
-	TOP = Fsubstring (TOP, arg1, arg2);
+	TOP_LVALUE = Fsubstring (TOP, arg1, arg2);
 	break;
       }
 
@@ -1504,11 +1557,11 @@
       break;
 
     case Bchar_after:
-      TOP = Fchar_after (TOP, Qnil);
+      TOP_LVALUE = Fchar_after (TOP, Qnil);
       break;
 
     case Bindent_to:
-      TOP = Findent_to (TOP, Qnil, Qnil);
+      TOP_LVALUE = Findent_to (TOP, Qnil, Qnil);
       break;
 
     case Bwiden:
@@ -1549,56 +1602,56 @@
       break;
 
     case Bforward_char:
-      TOP = Fforward_char (TOP, Qnil);
+      TOP_LVALUE = Fforward_char (TOP, Qnil);
       break;
 
     case Bforward_word:
-      TOP = Fforward_word (TOP, Qnil);
+      TOP_LVALUE = Fforward_word (TOP, Qnil);
       break;
 
     case Bforward_line:
-      TOP = Fforward_line (TOP, Qnil);
+      TOP_LVALUE = Fforward_line (TOP, Qnil);
       break;
 
     case Bchar_syntax:
-      TOP = Fchar_syntax (TOP, Qnil);
+      TOP_LVALUE = Fchar_syntax (TOP, Qnil);
       break;
 
     case Bbuffer_substring:
       {
 	Lisp_Object arg = POP;
-	TOP = Fbuffer_substring (TOP, arg, Qnil);
+	TOP_LVALUE = Fbuffer_substring (TOP, arg, Qnil);
 	break;
       }
 
     case Bdelete_region:
       {
 	Lisp_Object arg = POP;
-	TOP = Fdelete_region (TOP, arg, Qnil);
+	TOP_LVALUE = Fdelete_region (TOP, arg, Qnil);
 	break;
       }
 
     case Bnarrow_to_region:
       {
 	Lisp_Object arg = POP;
-	TOP = Fnarrow_to_region (TOP, arg, Qnil);
+	TOP_LVALUE = Fnarrow_to_region (TOP, arg, Qnil);
 	break;
       }
 
     case Bend_of_line:
-      TOP = Fend_of_line (TOP, Qnil);
+      TOP_LVALUE = Fend_of_line (TOP, Qnil);
       break;
 
     case Btemp_output_buffer_setup:
       temp_output_buffer_setup (TOP);
-      TOP = Vstandard_output;
+      TOP_LVALUE = Vstandard_output;
       break;
 
     case Btemp_output_buffer_show:
       {
 	Lisp_Object arg = POP;
 	temp_output_buffer_show (TOP, Qnil);
-	TOP = arg;
+	TOP_LVALUE = arg;
 	/* GAG ME!! */
 	/* pop binding of standard-output */
 	unbind_to (specpdl_depth() - 1);
@@ -1608,38 +1661,78 @@
     case Bold_eq:
       {
 	Lisp_Object arg = POP;
-	TOP = HACKEQ_UNSAFE (TOP, arg) ? Qt : Qnil;
+	TOP_LVALUE = HACKEQ_UNSAFE (TOP, arg) ? Qt : Qnil;
 	break;
       }
 
     case Bold_memq:
       {
 	Lisp_Object arg = POP;
-	TOP = Fold_memq (TOP, arg);
+	TOP_LVALUE = Fold_memq (TOP, arg);
 	break;
       }
 
     case Bold_equal:
       {
 	Lisp_Object arg = POP;
-	TOP = Fold_equal (TOP, arg);
+	TOP_LVALUE = Fold_equal (TOP, arg);
 	break;
       }
 
     case Bold_member:
       {
 	Lisp_Object arg = POP;
-	TOP = Fold_member (TOP, arg);
+	TOP_LVALUE = Fold_member (TOP, arg);
 	break;
       }
 
     case Bold_assq:
       {
 	Lisp_Object arg = POP;
-	TOP = Fold_assq (TOP, arg);
+	TOP_LVALUE = Fold_assq (TOP, arg);
 	break;
       }
 
+    case Bbind_multiple_value_limits:
+      {
+        Lisp_Object upper = POP, first = TOP, speccount;
+
+        CHECK_NATNUM (upper);
+        CHECK_NATNUM (first);
+
+        speccount = make_int (bind_multiple_value_limits (XINT (first),
+                                                          XINT (upper)));
+        PUSH (upper);
+        PUSH (speccount);
+        break;
+      }
+
+    case Bmultiple_value_call:
+      {
+        n = XINT (POP);
+        DISCARD_PRESERVING_MULTIPLE_VALUES (n - 1);
+        /* Discard multiple values for the first (function) argument: */
+        TOP_LVALUE = TOP;
+        TOP_LVALUE = multiple_value_call (n, TOP_ADDRESS);
+        break;
+      }
+
+    case Bmultiple_value_list_internal:
+      {
+        DISCARD_PRESERVING_MULTIPLE_VALUES (3);
+        TOP_LVALUE = multiple_value_list_internal (4, TOP_ADDRESS);
+        break;
+      }
+
+    case Bthrow:
+      {
+        Lisp_Object arg = POP_WITH_MULTIPLE_VALUES;
+        
+        /* We never throw to a catch tag that is a multiple value: */
+        throw_or_bomb_out (TOP, arg, 0, Qnil, Qnil);
+        break;
+      }
+
     default:
       ABORT();
       break;
--- a/src/callint.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/callint.c	Sun Aug 16 20:55:49 2009 +0100
@@ -400,7 +400,7 @@
 
       GCPRO3 (function, specs, input);
       /* Compute the arg values using the user's expression.  */
-      specs = Feval (specs);
+      specs = IGNORE_MULTIPLE_VALUES (Feval (specs));
       if (EQ (record_flag, Qlambda)) /* XEmacs addition */
 	{
 	  UNGCPRO;
@@ -916,7 +916,7 @@
 	    {
 	      Lisp_Object tem = call1 (Qread_expression, PROMPT ());
 	      /* visargs[argnum] = Fprin1_to_string (tem, Qnil); */
-	      args[argnum] = Feval (tem);
+              args[argnum] = IGNORE_MULTIPLE_VALUES (Feval (tem));
 	      arg_from_tty = 1;
 	      break;
 	    }
--- a/src/device-x.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/device-x.c	Sun Aug 16 20:55:49 2009 +0100
@@ -1280,7 +1280,8 @@
       enqueue_magic_eval_event (io_error_delete_device, dev);
       DEVICE_X_BEING_DELETED (d) = 1;
     }
-  Fthrow (Qtop_level, Qnil);
+
+  throw_or_bomb_out (Qtop_level, Qnil, 0, Qnil, Qnil);
 
   RETURN_NOT_REACHED (0);
 }
--- a/src/eval.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/eval.c	Sun Aug 16 20:55:49 2009 +0100
@@ -241,6 +241,16 @@
 Lisp_Object Vpending_warnings, Vpending_warnings_tail;
 Lisp_Object Qif;
 
+Lisp_Object Qthrow;
+Lisp_Object Qobsolete_throw;
+
+static int first_desired_multiple_value;
+/* Used outside this file, somewhat uncleanly, in the IGNORE_MULTIPLE_VALUES
+   macro: */
+int multiple_value_current_limit;
+
+Fixnum Vmultiple_values_limit;
+
 /* Flags specifying which operations are currently inhibited. */
 int inhibit_flags;
 
@@ -820,6 +830,9 @@
 The remaining ARGS are not evalled at all.
 If all args return nil, return nil.
 
+Any multiple values from the last form, and only from the last form, are
+passed back.  See `values' and `multiple-value-bind'. 
+
 arguments: (&rest ARGS)
 */
        (args))
@@ -827,13 +840,21 @@
   /* This function can GC */
   REGISTER Lisp_Object val;
 
-  LIST_LOOP_2 (arg, args)
+  LIST_LOOP_3 (arg, args, tail)
     {
-      if (!NILP (val = Feval (arg)))
-	return val;
+      if (!NILP (IGNORE_MULTIPLE_VALUES (val = Feval (arg))))
+	{
+	  if (NILP (XCDR (tail)))
+	    {
+	      /* Pass back multiple values if this is the last one: */
+	      return val;
+	    }
+
+	  return IGNORE_MULTIPLE_VALUES (val);
+	}
     }
 
-  return Qnil;
+  return val;
 }
 
 DEFUN ("and", Fand, 0, UNEVALLED, 0, /*
@@ -841,6 +862,9 @@
 The remaining ARGS are not evalled at all.
 If no arg yields nil, return the last arg's value.
 
+Any multiple values from the last form, and only from the last form, are
+passed back.  See `values' and `multiple-value-bind'. 
+
 arguments: (&rest ARGS)
 */
        (args))
@@ -848,10 +872,18 @@
   /* This function can GC */
   REGISTER Lisp_Object val = Qt;
 
-  LIST_LOOP_2 (arg, args)
+  LIST_LOOP_3 (arg, args, tail)
     {
-      if (NILP (val = Feval (arg)))
-	return val;
+      if (NILP (IGNORE_MULTIPLE_VALUES (val = Feval (arg))))
+	{
+	  if (NILP (XCDR (tail)))
+	    {
+	      /* Pass back any multiple values for the last form: */
+	      return val;
+	    }
+
+	  return Qnil;
+	}
     }
 
   return val;
@@ -872,7 +904,7 @@
   Lisp_Object then_form  = XCAR (XCDR (args));
   Lisp_Object else_forms = XCDR (XCDR (args));
 
-  if (!NILP (Feval (condition)))
+  if (!NILP (IGNORE_MULTIPLE_VALUES (Feval (condition))))
     return Feval (then_form);
   else
     return Fprogn (else_forms);
@@ -935,11 +967,12 @@
   LIST_LOOP_2 (clause, args)
     {
       CHECK_CONS (clause);
-      if (!NILP (val = Feval (XCAR (clause))))
+      if (!NILP (val = IGNORE_MULTIPLE_VALUES (Feval (XCAR (clause)))))
 	{
 	  if (!NILP (clause = XCDR (clause)))
 	    {
 	      CHECK_TRUE_LIST (clause);
+	      /* Pass back any multiple values here: */
 	      val = Fprogn (clause);
 	    }
 	  return val;
@@ -988,7 +1021,7 @@
   Lisp_Object val;
   struct gcpro gcpro1;
 
-  val = Feval (XCAR (args));
+  val = IGNORE_MULTIPLE_VALUES (Feval (Fcar (args)));
 
   GCPRO1 (val);
 
@@ -1017,7 +1050,9 @@
 
   Feval (XCAR (args));
   args = XCDR (args);
-  val = Feval (XCAR (args));
+
+  val = IGNORE_MULTIPLE_VALUES (Feval (XCAR (args)));
+
   args = XCDR (args);
 
   GCPRO1 (val);
@@ -1062,7 +1097,7 @@
 	  else
 	    {
 	      CHECK_CONS (tem);
-	      value = Feval (XCAR (tem));
+              value = IGNORE_MULTIPLE_VALUES (Feval (XCAR (tem)));
 	      if (!NILP (XCDR (tem)))
 		sferror
 		  ("`let' bindings can have only one value-form", var);
@@ -1120,7 +1155,7 @@
 	    else
 	      {
 		CHECK_CONS (tem);
-		*value = Feval (XCAR (tem));
+                *value = IGNORE_MULTIPLE_VALUES (Feval (XCAR (tem)));
 		gcpro1.nvars = idx;
 
 		if (!NILP (XCDR (tem)))
@@ -1157,7 +1192,7 @@
   Lisp_Object test = XCAR (args);
   Lisp_Object body = XCDR (args);
 
-  while (!NILP (Feval (test)))
+  while (!NILP (IGNORE_MULTIPLE_VALUES (Feval (test))))
     {
       QUIT;
       Fprogn (body);
@@ -1189,6 +1224,7 @@
   GC_PROPERTY_LIST_LOOP_3 (symbol, val, args)
     {
       val = Feval (val);
+      val = IGNORE_MULTIPLE_VALUES (val);
       Fset (symbol, val);
       retval = val;
     }
@@ -1311,7 +1347,7 @@
 	{
 	  struct gcpro gcpro1;
 	  GCPRO1 (val);
-	  val = Feval (val);
+	  val = IGNORE_MULTIPLE_VALUES (Feval (val));
 	  Fset_default (sym, val);
 	  UNGCPRO;
 	}
@@ -1361,6 +1397,8 @@
 
   GCPRO1 (val);
 
+  val = IGNORE_MULTIPLE_VALUES (val);
+
   Fset_default (sym, val);
 
   UNGCPRO;
@@ -1663,10 +1701,10 @@
   LONGJMP (c->jmp, 1);
 }
 
-static DECLARE_DOESNT_RETURN (throw_or_bomb_out (Lisp_Object, Lisp_Object, int,
-						 Lisp_Object, Lisp_Object));
-
-static DOESNT_RETURN
+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)
 {
@@ -1739,12 +1777,29 @@
    condition_case_1).  See below for more info.
 */
 
-DEFUN_NORETURN ("throw", Fthrow, 2, 2, 0, /*
+DEFUN_NORETURN ("throw", Fthrow, 2, UNEVALLED, 0, /*
 Throw to the catch for TAG and return VALUE from it.
-Both TAG and VALUE are evalled.  Tags are the same iff they are `eq'.
+
+Both TAG and VALUE are evalled, and multiple values in VALUE will be passed
+back.  Tags are the same if and only if they are `eq'.
+
+arguments: (TAG VALUE)
 */
-       (tag, value))
-{
+       (args))
+{
+  int nargs;
+  Lisp_Object tag, value;
+
+  GET_LIST_LENGTH (args, nargs);
+  if (nargs != 2)
+    {
+      Fsignal (Qwrong_number_of_arguments, list2 (Qthrow, make_int (nargs)));
+    }
+
+  tag = IGNORE_MULTIPLE_VALUES (Feval (XCAR(args)));
+
+  value = Feval (XCAR (XCDR (args)));
+
   throw_or_bomb_out (tag, value, 0, Qnil, Qnil); /* Doesn't return */
   RETURN_NOT_REACHED (Qnil);
 }
@@ -2360,7 +2415,8 @@
       else if (EQ (handler_data, Qt))
 	{
           UNGCPRO;
-          return Fthrow (handlers, Fcons (error_symbol, data));
+          throw_or_bomb_out (handlers, Fcons (error_symbol, data),
+                             0, Qnil, Qnil);
 	}
       /* `error' is used similarly to the way `t' is used, but in
          addition it invokes the debugger if debug_on_error.
@@ -2379,7 +2435,7 @@
             return return_from_signal (tem);
 
           tem = Fcons (error_symbol, data);
-          return Fthrow (handlers, tem);
+          throw_or_bomb_out (handlers, tem, 0, Qnil, Qnil);
         }
       else
 	{
@@ -2403,7 +2459,7 @@
 
                   /* Doesn't return */
                   tem = Fcons (Fcons (error_symbol, data), Fcdr (clause));
-                  return Fthrow (handlers, tem);
+                  throw_or_bomb_out (handlers, tem, 0, Qnil, Qnil);
                 }
 	    }
 	}
@@ -3665,7 +3721,7 @@
 	  {
 	    LIST_LOOP_2 (arg, original_args)
 	      {
-		*p++ = Feval (arg);
+                *p++ = IGNORE_MULTIPLE_VALUES (Feval (arg));
 		gcpro1.nvars++;
 	      }
 	  }
@@ -3696,7 +3752,7 @@
 	  {
 	    LIST_LOOP_2 (arg, original_args)
 	      {
-		*p++ = Feval (arg);
+                *p++ = IGNORE_MULTIPLE_VALUES (Feval (arg));
 		gcpro1.nvars++;
 	      }
 	  }
@@ -3729,7 +3785,7 @@
       {
 	LIST_LOOP_2 (arg, original_args)
 	  {
-	    *p++ = Feval (arg);
+            *p++ = IGNORE_MULTIPLE_VALUES (Feval (arg));
 	    gcpro1.nvars++;
 	  }
       }
@@ -3778,7 +3834,7 @@
 	  {
 	    LIST_LOOP_2 (arg, original_args)
 	      {
-		*p++ = Feval (arg);
+                *p++ = IGNORE_MULTIPLE_VALUES (Feval (arg));
 		gcpro1.nvars++;
 	      }
 	  }
@@ -3958,6 +4014,12 @@
 	}
       else if (max_args == UNEVALLED) /* Can't funcall a special form */
 	{
+          /* Ugh, ugh, ugh. */
+          if (EQ (fun, XSYMBOL_FUNCTION (Qthrow)))
+            {
+              args[0] = Qobsolete_throw;
+              goto retry;
+            }
 	  goto invalid_function;
 	}
       else
@@ -4238,7 +4300,6 @@
   }
 }
 
-
 /* Apply lambda list FUN to the NARGS evaluated arguments in ARGS and
    return the result of evaluation. */
 
@@ -4296,6 +4357,590 @@
 }
 
 
+/* Multiple values. 
+
+   A multiple value object is returned by #'values if:
+
+   -- The number of arguments to #'values is not one, and: 
+   -- Some special form in the call stack is prepared to handle more than
+   one multiple value.
+   
+   The return value of #'values-list is analogous to that of #'values.
+
+   Henry Baker, in https://eprints.kfupm.edu.sa/31898/1/31898.pdf ("CONS
+   Should not CONS its Arguments, or, a Lazy Alloc is a Smart Alloc", ACM
+   Sigplan Notices 27,3 (March 1992),24-34.) says it should be possible to
+   allocate Common Lisp multiple-value objects on the stack, but this
+   assumes that variable-length records can be allocated on the stack,
+   something not true for us. As far as I can tell, it also ignores the
+   contexts where multiple-values need to be thrown, or maybe it thinks such
+   objects should be converted to heap allocation at that point.
+
+   The specific multiple values saved and returned depend on how many
+   multiple-values special forms in the stack are interested in; for
+   example, if #'multiple-value-call is somewhere in the call stack, all
+   values passed to #'values will be saved and returned.  If an expansion of
+   #'multiple-value-setq with 10 SYMS is the only part of the call stack
+   interested in multiple values, then a maximum of ten multiple values will
+   be saved and returned.
+
+   (#'throw passes back multiple values in its VALUE argument; this is why
+   we can't just take the details of the most immediate
+   #'multiple-value-{whatever} call to work out which values to save, we
+   need to look at the whole stack, or, equivalently, the dynamic variables
+   we set to reflect the whole stack.)
+
+   The first value passed to #'values will always be saved, since that is
+   needed to convert a multiple value object into a single value object,
+   something that is normally necessary independent of how many functions in
+   the call stack are interested in multiple values.
+
+   However many values (for values of "however many" that are not one) are
+   saved and restored, the multiple value object knows how many arguments it
+   would contain were none to have been discarded, and will indicate this
+   on being printed from within GDB.
+
+   In lisp-interaction-mode, no multiple values should be discarded (unless
+   they need to be for the sake of the correctness of the program);
+   #'eval-interactive-with-multiple-value-list in lisp-mode.el wraps its
+   #'eval calls with #'multiple-value-list calls to avoid this. This means
+   that there is a small performance and memory penalty for code evaluated
+   in *scratch*; use M-: EXPRESSION RET if you really need to avoid
+   this. Lisp code execution that is not ultimately from hitting C-j in
+   *scratch*--that is, the vast vast majority of Lisp code execution--does
+   not have this penalty.
+
+   Probably the most important aspect of multiple values is stated with
+   admirable clarity by CLTL2:
+
+     "No matter how many values a form produces, if the form is an argument
+     form in a function call, then exactly one value (the first one) is
+     used."
+   
+   This means that most contexts, most of the time, will never see multiple
+   values.  There are important exceptions; search the web for that text in
+   quotation marks and read the related chapter. This code handles all of
+   them, to my knowledge. Aidan Kehoe, Mon Mar 16 00:17:39 GMT 2009. */
+
+static Lisp_Object
+make_multiple_value (Lisp_Object first_value, Elemcount count,
+                     Elemcount first_desired, Elemcount upper_limit)
+{
+  Bytecount sizem;
+  struct multiple_value *mv;
+  Elemcount i, allocated_count;
+
+  assert (count != 1);
+
+  if (1 != upper_limit && (0 == first_desired))
+    {
+      /* We always allocate element zero, and that's taken into account when
+         working out allocated_count: */
+      first_desired = 1;
+    }
+
+  if (first_desired >= count)
+    {
+      /* We can't pass anything back that our caller is interested in. Only
+         allocate for the first argument. */
+      allocated_count = 1;
+    }
+  else
+    {
+      allocated_count = 1 + ((upper_limit > count ? count : upper_limit)
+                             - first_desired);
+    }
+
+  sizem = FLEXIBLE_ARRAY_STRUCT_SIZEOF (multiple_value,
+                                        Lisp_Object,
+                                        contents, allocated_count);
+  mv = (multiple_value *) BASIC_ALLOC_LCRECORD (sizem,
+                                                &lrecord_multiple_value);
+
+  mv->count = count;
+  mv->first_desired = first_desired;
+  mv->allocated_count = allocated_count;
+  mv->contents[0] = first_value;
+
+  for (i = first_desired; i < upper_limit && i < count; ++i)
+    {
+      mv->contents[1 + (i - first_desired)] = Qunbound;
+    }
+
+  return wrap_multiple_value (mv);
+}
+
+void
+multiple_value_aset (Lisp_Object obj, Elemcount index, Lisp_Object value)
+{
+  struct multiple_value *mv = XMULTIPLE_VALUE (obj);
+  Elemcount first_desired = mv->first_desired; 
+  Elemcount allocated_count = mv->allocated_count; 
+
+  if (index != 0 &&
+      (index < first_desired || index >= (first_desired + allocated_count)))
+    {
+      args_out_of_range (make_int (first_desired),
+                         make_int (first_desired + allocated_count));
+    }
+
+  mv->contents[index == 0 ? 0 : 1 + (index - first_desired)] = value;
+}
+
+Lisp_Object
+multiple_value_aref (Lisp_Object obj, Elemcount index)
+{
+  struct multiple_value *mv = XMULTIPLE_VALUE (obj);
+  Elemcount first_desired = mv->first_desired; 
+  Elemcount allocated_count = mv->allocated_count; 
+
+  if (index != 0 &&
+      (index < first_desired || index >= (first_desired + allocated_count)))
+    {
+      args_out_of_range (make_int (first_desired),
+                         make_int (first_desired + allocated_count));
+    }
+
+  return mv->contents[index == 0 ? 0 : 1 + (index - first_desired)];
+}
+
+static void
+print_multiple_value (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
+{
+  struct multiple_value *mv = XMULTIPLE_VALUE (obj);
+  Elemcount first_desired = mv->first_desired; 
+  Elemcount allocated_count = mv->allocated_count; 
+  Elemcount count = mv->count, index;
+
+  if (print_readably)
+    {
+      printing_unreadable_object ("multiple values");
+    }
+
+  if (0 == count)
+    {
+      write_c_string (printcharfun, "#<zero-length multiple value>");
+    }
+
+  for (index = 0; index < count;)
+    {
+      if (index != 0 &&
+          (index < first_desired ||
+           index >= (first_desired + (allocated_count - 1))))
+        {
+          write_fmt_string (printcharfun, "#<discarded-multiple-value %d>",
+                            index);
+        }
+      else
+        {
+          print_internal (multiple_value_aref (obj, index),
+                          printcharfun, escapeflag);
+        }
+
+      ++index;
+
+      if (count > 1 && index < count)
+        {
+          write_c_string (printcharfun, " ;\n");
+        }
+    }
+}
+
+static Lisp_Object
+mark_multiple_value (Lisp_Object obj)
+{
+  struct multiple_value *mv = XMULTIPLE_VALUE (obj);
+  Elemcount index, allocated_count = mv->allocated_count;
+
+  for (index = 0; index < allocated_count; ++index)
+    {
+      mark_object (mv->contents[index]);
+    }
+
+  return Qnil;
+}
+
+static Bytecount
+size_multiple_value (const void *lheader)
+{
+  return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct multiple_value,
+                                       Lisp_Object, contents,
+                                       ((struct multiple_value *) lheader)->
+                                       allocated_count);
+}
+
+static const struct memory_description multiple_value_description[] = {
+  { XD_LONG, offsetof (struct multiple_value, count) },
+  { XD_ELEMCOUNT, offsetof (struct multiple_value, allocated_count) },
+  { XD_LONG, offsetof (struct multiple_value, first_desired) },
+  { XD_LISP_OBJECT_ARRAY, offsetof (struct multiple_value, contents),
+    XD_INDIRECT (1, 0) },
+  { XD_END }
+};
+
+DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("multiple-value", multiple_value,
+					1, /*dumpable-flag*/
+					mark_multiple_value,
+                                        print_multiple_value, 0,
+					0, /* No equal method. */
+					0, /* No hash method. */
+					multiple_value_description,
+					size_multiple_value,
+                                        struct multiple_value);
+
+/* Given that FIRST and UPPER are the inclusive lower and exclusive upper
+   bounds for the multiple values we're interested in, modify (or don't) the
+   special variables used to indicate this to #'values and #'values-list.
+   Returns the specpdl_depth() value before any modification. */
+int
+bind_multiple_value_limits (int first, int upper)
+{
+  int result = specpdl_depth();
+
+  if (!(upper > first))
+    {
+      invalid_argument ("MULTIPLE-VALUE-UPPER-LIMIT must be greater than "
+                        " FIRST-DESIRED-MULTIPLE-VALUE", Qunbound);
+    }
+
+  if (upper > Vmultiple_values_limit)
+    {
+      args_out_of_range (make_int (upper), make_int (Vmultiple_values_limit));
+    }
+
+  /* In the event that something back up the stack wants more multiple
+     values than we do, we need to keep its figures for
+     first_desired_multiple_value or multiple_value_current_limit both. It
+     may be that the form will throw past us.
+
+     If first_desired_multiple_value is zero, this means it hasn't ever been
+     bound, and any value we have for first is appropriate to use.
+
+     Zeroth element is always saved, no need to note that: */
+  if (0 == first)
+    {
+      first = 1;
+    }
+
+  if (0 == first_desired_multiple_value
+      || first < first_desired_multiple_value)
+    {
+      internal_bind_int (&first_desired_multiple_value, first);      
+    }
+
+  if (upper > multiple_value_current_limit)
+    {
+      internal_bind_int (&multiple_value_current_limit, upper);
+    }
+
+  return result;
+}
+
+Lisp_Object
+multiple_value_call (int nargs, Lisp_Object *args)
+{
+  /* The argument order here is horrible: */
+  int i, speccount = XINT (args[3]);
+  Lisp_Object result = Qnil, head = Fcons (args[0], Qnil), list_offset; 
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object apply_args[2];
+  
+  GCPRO2 (head, result);
+  list_offset = head;
+
+  assert (!(MULTIPLE_VALUEP (args[0])));
+  CHECK_FUNCTION (args[0]);
+
+  /* Start at 4, to ignore the function, the speccount, and the arguments to
+     multiple-values-limit (which we don't discard because
+     #'multiple-value-list-internal needs them): */
+  for (i = 4; i < nargs; ++i)
+    {
+      result = args[i];
+      if (MULTIPLE_VALUEP (result))
+        {
+          Lisp_Object val;
+          Elemcount i, count = XMULTIPLE_VALUE_COUNT (result);
+
+          for (i = 0; i < count; i++)
+            {
+              val = multiple_value_aref (result, i);
+              assert (!UNBOUNDP (val));
+
+              XSETCDR (list_offset, Fcons (val, Qnil));
+              list_offset = XCDR (list_offset);
+            }
+        }
+      else
+        {
+          XSETCDR (list_offset, Fcons (result, Qnil));
+          list_offset = XCDR (list_offset);
+        }
+    }
+
+  apply_args [0] = XCAR (head);
+  apply_args [1] = XCDR (head);
+
+  unbind_to (speccount);
+
+  RETURN_UNGCPRO (Fapply (countof(apply_args), apply_args));
+}
+
+DEFUN ("multiple-value-call", Fmultiple_value_call, 1, UNEVALLED, 0, /*
+Call FUNCTION with arguments FORMS, using multiple values when returned.
+
+All of the (possibly multiple) values returned by each form in FORMS are
+gathered together, and given as arguments to FUNCTION; conceptually, this
+function is a version of `apply' that by-passes the multiple values
+infrastructure, treating multiple values as intercalated lists.
+
+arguments: (FUNCTION &rest FORMS)
+*/
+       (args))
+{
+  int listcount, i = 0, speccount;
+  Lisp_Object *constructed_args;
+  struct gcpro gcpro1;
+
+  GET_EXTERNAL_LIST_LENGTH (args, listcount);
+
+  constructed_args = alloca_array (Lisp_Object, listcount + 3);
+
+  /* Fcar so we error on non-cons: */
+  constructed_args[i] = IGNORE_MULTIPLE_VALUES (Feval (Fcar (args)));
+
+  GCPRO1 (*constructed_args);
+  gcpro1.nvars = ++i; 
+
+  /* The argument order is horrible here. */
+  constructed_args[i] = make_int (0);
+  gcpro1.nvars = ++i;
+  constructed_args[i] = make_int (Vmultiple_values_limit);
+  gcpro1.nvars = ++i;
+
+  speccount = bind_multiple_value_limits (0, Vmultiple_values_limit);
+  constructed_args[i] = make_int (speccount);
+  gcpro1.nvars = ++i;
+
+  {
+    LIST_LOOP_2 (elt, XCDR (args))
+      {
+        constructed_args[i] = Feval (elt);
+        gcpro1.nvars = ++i;
+      }
+  }
+
+  RETURN_UNGCPRO (multiple_value_call (listcount + 3, constructed_args));
+}
+
+Lisp_Object
+multiple_value_list_internal (int nargs, Lisp_Object *args)
+{
+  int first = XINT (args[0]), upper = XINT (args[1]),
+    speccount = XINT(args[2]);
+  Lisp_Object result = Qnil;
+
+  assert (nargs == 4);
+
+  result = args[3];
+
+  unbind_to (speccount); 
+
+  if (MULTIPLE_VALUEP (result))
+    {
+      Lisp_Object head = Fcons (Qnil, Qnil);
+      Lisp_Object list_offset = head, val; 
+      Elemcount count = XMULTIPLE_VALUE_COUNT(result);
+      
+      for (; first < upper && first < count; ++first)
+        {
+          val = multiple_value_aref (result, first);
+          assert (!UNBOUNDP (val));
+
+          XSETCDR (list_offset, Fcons (val, Qnil));
+          list_offset = XCDR (list_offset);
+        }
+
+      return XCDR (head);
+    }
+  else
+    {
+      if (first == 0)
+	{
+          return Fcons (result, Qnil);
+        }
+      else
+        {
+          return Qnil;
+        }
+    }
+}
+
+DEFUN ("multiple-value-list-internal", Fmultiple_value_list_internal, 3,
+       UNEVALLED, 0, /*
+Evaluate FORM. Return a list of multiple vals reflecting the other two args.
+
+Don't use this.  Use `multiple-value-list', the macro specified by Common
+Lisp, instead.
+
+FIRST-DESIRED-MULTIPLE-VALUE is the first element in list of multiple values
+to pass back.  MULTIPLE-VALUE-UPPER-LIMIT is the exclusive upper limit on
+the indexes within the values that may be passed back; this function will
+never return a list longer than MULTIPLE-VALUE-UPPER-LIMIT -
+FIRST-DESIRED-MULTIPLE-VALUE.  It may return a list shorter than that, if
+`values' or `values-list' do not supply enough elements.
+
+arguments: (FIRST-DESIRED-MULTIPLE-VALUE MULTIPLE-VALUE-UPPER-LIMIT FORM)
+*/
+       (args))
+{
+  Lisp_Object argv[4];
+  int first, upper;
+  struct gcpro gcpro1;
+
+  argv[0] = IGNORE_MULTIPLE_VALUES (Feval (XCAR (args)));
+  CHECK_NATNUM (argv[0]);
+  first = XINT (argv[0]);
+
+  GCPRO1 (argv[0]);
+  gcpro1.nvars = 1;
+
+  args = XCDR (args);
+
+  argv[1] = IGNORE_MULTIPLE_VALUES (Feval (XCAR (args)));
+  CHECK_NATNUM (argv[1]);
+  upper = XINT (argv[1]);
+  gcpro1.nvars = 2;
+
+  /* The unintuitive order of things here is for the sake of the bytecode;
+     the alternative would be to encode the number of arguments in the
+     bytecode stream, which complicates things if we have more than 255
+     arguments. */
+  argv[2] = make_int (bind_multiple_value_limits (first, upper));
+  gcpro1.nvars = 3;
+  args = XCDR (args);
+
+  /* GCPROing in this function is not strictly necessary, this Feval is the
+     only point that may cons up data that is not immediately discarded, and
+     within it is the only point (in Fmultiple_value_list_internal and
+     multiple_value_list) that we can garbage collect. But I'm conservative,
+     and this function is called so rarely (only from interpreted code) that
+     it doesn't matter for performance. */
+  argv[3] = Feval (XCAR (args));
+  gcpro1.nvars = 4;
+
+  RETURN_UNGCPRO (multiple_value_list_internal (countof (argv), argv));
+}
+
+DEFUN ("multiple-value-prog1", Fmultiple_value_prog1, 1, UNEVALLED, 0, /*
+Similar to `prog1', but return any multiple values from the first form. 
+`prog1' itself will never return multiple values. 
+
+arguments: (FIRST &rest BODY)
+*/
+       (args))
+{
+  /* This function can GC */
+  Lisp_Object val;
+  struct gcpro gcpro1;
+
+  val = Feval (XCAR (args));
+
+  GCPRO1 (val);
+
+  {
+    LIST_LOOP_2 (form, XCDR (args))
+      Feval (form);
+  }
+
+  RETURN_UNGCPRO (val); 
+}  
+
+DEFUN ("values", Fvalues, 0, MANY, 0, /*
+Return all ARGS as multiple values.
+
+arguments: (&rest ARGS)
+*/
+       (int nargs, Lisp_Object *args))
+{
+  Lisp_Object result = Qnil;
+  int counting = 1;
+
+  /* Pathological cases, no need to cons up an object: */
+  if (1 == nargs || 1 == multiple_value_current_limit)
+    {
+      return nargs ? args[0] : Qnil;
+    }
+
+  /* If nargs is zero, this code is correct and desirable.  With
+     #'multiple-value-call, we want zero-length multiple values in the
+     argument list to be discarded entirely, and we can't do this if we
+     transform them to nil. */
+  result = make_multiple_value (nargs ? args[0] : Qnil, nargs, 
+                                first_desired_multiple_value,
+                                multiple_value_current_limit);
+
+  for (; counting < nargs; ++counting)
+    {
+      if (counting >= first_desired_multiple_value &&
+          counting < multiple_value_current_limit)
+        {
+          multiple_value_aset (result, counting, args[counting]);
+        }
+    }
+
+  return result;
+}
+
+DEFUN ("values-list", Fvalues_list, 1, 1, 0, /*
+Return all the elements of LIST as multiple values.
+*/
+       (list))
+{
+  Lisp_Object result = Qnil;
+  int counting = 1, listcount; 
+
+  GET_EXTERNAL_LIST_LENGTH (list, listcount);
+
+  /* Pathological cases, no need to cons up an object: */
+  if (1 == listcount || 1 == multiple_value_current_limit)
+    {
+      return Fcar_safe (list);
+    }
+
+  result = make_multiple_value (Fcar_safe (list), listcount,
+                                first_desired_multiple_value,
+                                multiple_value_current_limit);
+
+  list = Fcdr_safe (list);
+
+  {
+    EXTERNAL_LIST_LOOP_2 (elt, list)
+      {
+        if (counting >= first_desired_multiple_value &&
+            counting < multiple_value_current_limit)
+          {
+            multiple_value_aset (result, counting, elt);
+          }
+        ++counting;
+      }
+    }
+
+  return result;
+}
+
+Lisp_Object
+values2 (Lisp_Object first, Lisp_Object second)
+{
+  Lisp_Object argv[2];
+
+  argv[0] = first;
+  argv[1] = second;
+
+  return Fvalues (countof (argv), argv);
+}
+
+
 /************************************************************************/
 /*		     Run hook variables in various ways.		*/
 /************************************************************************/
@@ -4968,7 +5613,7 @@
   p->error_conditions = error_conditions;
   p->data = data;
 
-  Fthrow (p->catchtag, Qnil);
+  throw_or_bomb_out (p->catchtag, Qnil, 0, Qnil, Qnil);
   RETURN_NOT_REACHED (Qnil);
 }
 
@@ -6555,6 +7200,7 @@
 syms_of_eval (void)
 {
   INIT_LRECORD_IMPLEMENTATION (subr);
+  INIT_LRECORD_IMPLEMENTATION (multiple_value);
 
   DEFSYMBOL (Qinhibit_quit);
   DEFSYMBOL (Qautoload);
@@ -6578,6 +7224,8 @@
   DEFSYMBOL (Qrun_hooks);
   DEFSYMBOL (Qfinalize_list);
   DEFSYMBOL (Qif);
+  DEFSYMBOL (Qthrow);
+  DEFSYMBOL (Qobsolete_throw);  
 
   DEFSUBR (For);
   DEFSUBR (Fand);
@@ -6611,6 +7259,11 @@
   DEFSUBR (Fautoload);
   DEFSUBR (Feval);
   DEFSUBR (Fapply);
+  DEFSUBR (Fmultiple_value_call);
+  DEFSUBR (Fmultiple_value_list_internal);
+  DEFSUBR (Fmultiple_value_prog1);
+  DEFSUBR (Fvalues);
+  DEFSUBR (Fvalues_list);
   DEFSUBR (Ffuncall);
   DEFSUBR (Ffunctionp);
   DEFSUBR (Ffunction_min_args);
@@ -6636,6 +7289,9 @@
   debug_on_next_call = 0;
   lisp_eval_depth = 0;
   entering_debugger = 0;
+
+  first_desired_multiple_value = 0;
+  multiple_value_current_limit = 1;
 }
 
 void
@@ -6805,6 +7461,14 @@
 */ );
   Vdebugger = Qnil;
 
+  DEFVAR_CONST_INT ("multiple-values-limit", &Vmultiple_values_limit /*
+The exclusive upper bound on the number of multiple values. 
+
+This applies to `values', `values-list', `multiple-value-bind' and related
+macros and special forms.
+*/);
+  Vmultiple_values_limit = EMACS_INT_MAX > INT_MAX ? INT_MAX : EMACS_INT_MAX;
+
   staticpro (&Vcatch_everything_tag);
   Vcatch_everything_tag = make_opaque (OPAQUE_CLEAR, 0);
 
--- a/src/event-msw.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/event-msw.c	Sun Aug 16 20:55:49 2009 +0100
@@ -1769,7 +1769,7 @@
     return Qnil;
 
   GCPRO1 (obj);
-  obj = Feval (XCAR (obj));
+  obj = IGNORE_MULTIPLE_VALUES (Feval (XCAR (obj)));
 
   RETURN_UNGCPRO (obj);
 }
--- a/src/event-stream.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/event-stream.c	Sun Aug 16 20:55:49 2009 +0100
@@ -843,7 +843,7 @@
 			 call1 (Qcurrent_window_configuration, Qnil));
   reset_key_echo (command_builder, 1);
 
-  help = Feval (Vhelp_form);
+  help = IGNORE_MULTIPLE_VALUES (Feval (Vhelp_form));
   if (STRINGP (help))
     internal_with_output_to_temp_buffer (build_string ("*Help*"),
 					 print_help, help, Qnil);
--- a/src/glade.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/glade.c	Sun Aug 16 20:55:49 2009 +0100
@@ -42,7 +42,8 @@
 
   if (signal_data && signal_data[0])
     {
-      lisp_data = Feval (Fread (build_string (signal_data)));
+      lisp_data
+        = IGNORE_MULTIPLE_VALUES (Feval (Fread (build_string (signal_data))));
     }
 
   /* obj, name, func, cb_data, object_signal, after_p */
--- a/src/glyphs-widget.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/glyphs-widget.c	Sun Aug 16 20:55:49 2009 +0100
@@ -222,7 +222,7 @@
     glyph = XSYMBOL (glyph)->value;
 
   if (CONSP (glyph))
-    glyph = Feval (glyph);
+    glyph = IGNORE_MULTIPLE_VALUES (Feval (glyph));
 
   /* Be really helpful to the user. */
   if (VECTORP (glyph))
--- a/src/glyphs.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/glyphs.c	Sun Aug 16 20:55:49 2009 +0100
@@ -3079,7 +3079,7 @@
       value = XCDR (cons);
       CHECK_CONS (value);
       value = XCAR (value);
-      value = Feval (value);
+      value = IGNORE_MULTIPLE_VALUES (Feval (value));
       if (NILP (value))
 	continue;
       if (!STRINGP (value) && !COLOR_SPECIFIERP (value))
--- a/src/gui-x.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/gui-x.c	Sun Aug 16 20:55:49 2009 +0100
@@ -325,8 +325,9 @@
   Lisp_Object wses_form = (form);					\
   (slot) = (NILP (wses_form) ? 0 :					\
 	    EQ (wses_form, Qt) ? 1 :					\
-	    !NILP (in_display ? eval_within_redisplay (wses_form)	\
-		   : Feval (wses_form)));				\
+	    !NILP (in_display ?                                         \
+                   IGNORE_MULTIPLE_VALUES (eval_within_redisplay (wses_form)) \
+		   : IGNORE_MULTIPLE_VALUES (Feval (wses_form))));      \
 } while (0)
 #else
   /* Treat the activep slot of the menu item as a boolean */
@@ -436,7 +437,7 @@
 #endif /* HAVE_MENUBARS */
 
   if (!STRINGP (pgui->name))
-    pgui->name = Feval (pgui->name);
+    pgui->name = IGNORE_MULTIPLE_VALUES (Feval (pgui->name));
 
   CHECK_STRING (pgui->name);
   if (accel_p)
@@ -459,7 +460,7 @@
 	suffix2 = pgui->suffix;
       else
 	{
-	  suffix2 = Feval (pgui->suffix);
+	  suffix2 = IGNORE_MULTIPLE_VALUES (Feval (pgui->suffix));
 	  CHECK_STRING (suffix2);
 	}
 
--- a/src/gui.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/gui.c	Sun Aug 16 20:55:49 2009 +0100
@@ -386,7 +386,6 @@
 gui_item_value (Lisp_Object form)
 {
   /* This function can call Lisp. */
-
 #ifndef ERROR_CHECK_DISPLAY
   /* Shortcut to avoid evaluating Qt/Qnil each time; but don't do it when
      error-checking so we catch unprotected eval within redisplay quicker */
@@ -395,7 +394,9 @@
   if (EQ (form, Qt))
     return 1;
 #endif
-  return !NILP (in_display ? eval_within_redisplay (form) : Feval (form));
+  return !NILP (in_display ?
+                IGNORE_MULTIPLE_VALUES (eval_within_redisplay (form))
+                : IGNORE_MULTIPLE_VALUES (Feval (form)));
 }
 
 /*
@@ -511,6 +512,7 @@
       if (!STRINGP (suffix))
 	{
 	  suffix = Feval (suffix);
+          suffix = IGNORE_MULTIPLE_VALUES (suffix);
 	  CHECK_STRING (suffix);
 	}
 
--- a/src/inline.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/inline.c	Sun Aug 16 20:55:49 2009 +0100
@@ -64,6 +64,7 @@
 #include "process.h"
 #include "rangetab.h"
 #include "specifier.h"
+#include "symeval.h"
 #include "syntax.h"
 #include "window.h"
 
--- a/src/lisp.h	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/lisp.h	Sun Aug 16 20:55:49 2009 +0100
@@ -4269,11 +4269,15 @@
 EXFUN (Finteractive_p, 0);
 EXFUN (Fprogn, UNEVALLED);
 MODULE_API EXFUN (Fsignal, 2);
-MODULE_API EXFUN_NORETURN (Fthrow, 2);
+MODULE_API EXFUN_NORETURN (Fthrow, UNEVALLED);
 MODULE_API EXFUN (Fcall_with_condition_handler, MANY);
 EXFUN (Ffunction_max_args, 1);
 EXFUN (Ffunction_min_args, 1);
 
+MODULE_API DECLARE_DOESNT_RETURN (throw_or_bomb_out (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);
--- a/src/lread.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/lread.c	Sun Aug 16 20:55:49 2009 +0100
@@ -372,7 +372,7 @@
 		  Lisp_Object val;
 
 		  GCPRO1 (reloc);
-		  val = Feval (XCDR (acons));
+		  val = IGNORE_MULTIPLE_VALUES (Feval (XCDR (acons)));
 		  UNGCPRO;
 
 		  if (!NILP (val))
--- a/src/lrecord.h	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/lrecord.h	Sun Aug 16 20:55:49 2009 +0100
@@ -224,6 +224,7 @@
   lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local,
   lrecord_type_symbol,
   lrecord_type_subr,
+  lrecord_type_multiple_value,
   lrecord_type_cons,
   lrecord_type_vector,
   lrecord_type_string,
--- a/src/macros.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/macros.c	Sun Aug 16 20:55:49 2009 +0100
@@ -197,7 +197,7 @@
 					  with Qt to force an early exit. */
     signal_error (Qinvalid_state, "junk in executing-macro", Qunbound);
 
-  Fthrow (Qexecute_kbd_macro, Qt);
+  throw_or_bomb_out (Qexecute_kbd_macro, Qt, 0, Qnil, Qnil);
 }
 
 
--- a/src/menubar-gtk.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/menubar-gtk.c	Sun Aug 16 20:55:49 2009 +0100
@@ -666,13 +666,14 @@
 
       if ((!NILP (config_tag)
 	   && NILP (Fmemq (config_tag, Vmenubar_configuration)))
-	  || (included_spec && NILP (Feval (include_p))))
+	  || (included_spec &&
+              NILP (IGNORE_MULTIPLE_VALUES (Feval (include_p)))))
 	{
 	  return (NULL);
 	}
 
       if (active_spec)
-	active_p = Feval (active_p);
+        active_p = IGNORE_MULTIPLE_VALUES (Feval (active_p));
 
       gtk_widget_set_sensitive (GTK_WIDGET (menu_item), ! NILP (active_p));
     }
@@ -853,7 +854,8 @@
 
 #ifdef HAVE_MENUBARS
       if ((!NILP (config_tag) && NILP (Fmemq (config_tag, Vmenubar_configuration)))
-	  || (included_spec && NILP (Feval (include_p))))
+	  || (included_spec && NILP (IGNORE_MULTIPLE_VALUES (Feval (include_p)))))
+
 	{
 	  /* the include specification says to ignore this item. */
 	  return 0;
@@ -866,7 +868,8 @@
 	accel = menu_name_to_accelerator (XSTRING_DATA (name));
 
       if (!NILP (suffix))
-	suffix = Feval (suffix);
+        suffix = IGNORE_MULTIPLE_VALUES (Feval (suffix));
+
 
       if (!separator_string_p (XSTRING_DATA (name)))
 	{
@@ -901,7 +904,7 @@
 	    }
 	  else
 	    {
-	      selected_p = Feval (selected_p);
+              selected_p = IGNORE_MULTIPLE_VALUES (Feval (selected_p));
 	    }
 	}
 
@@ -911,7 +914,7 @@
 	}
       else
 	{
-	  active_p = Feval (active_p);
+          active_p = IGNORE_MULTIPLE_VALUES (Feval (active_p));
 	}
 
       if (0 || 
--- a/src/menubar-msw.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/menubar-msw.c	Sun Aug 16 20:55:49 2009 +0100
@@ -326,7 +326,7 @@
 	}
 
       if (!STRINGP (pgui_item->name))
-	pgui_item->name = Feval (pgui_item->name);
+        pgui_item->name = IGNORE_MULTIPLE_VALUES (Feval (pgui_item->name));
 
       if (!gui_item_active_p (gui_item))
 	item_info.fState = MFS_GRAYED;
--- a/src/print.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/print.c	Sun Aug 16 20:55:49 2009 +0100
@@ -821,7 +821,7 @@
 #endif
 
   GCPRO2 (name, val);
-  name = Feval (XCAR (args));
+  name = IGNORE_MULTIPLE_VALUES (Feval (XCAR (args)));
 
   CHECK_STRING (name);
 
--- a/src/symbols.c	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/symbols.c	Sun Aug 16 20:55:49 2009 +0100
@@ -2146,7 +2146,7 @@
 
   GC_PROPERTY_LIST_LOOP_3 (symbol, val, args)
     {
-      val = Feval (val);
+      val = IGNORE_MULTIPLE_VALUES (Feval (val));
       Fset_default (symbol, val);
       retval = val;
     }
--- a/src/symeval.h	Sun Aug 16 14:58:57 2009 +0100
+++ b/src/symeval.h	Sun Aug 16 20:55:49 2009 +0100
@@ -488,6 +488,83 @@
 
 void flush_all_buffer_local_cache (void);
 
+struct multiple_value {
+  struct LCRECORD_HEADER header;
+  Elemcount count;
+  Elemcount allocated_count; 
+  Elemcount first_desired;
+  Lisp_Object contents[1];
+};
+typedef struct multiple_value multiple_value;
+
+DECLARE_LRECORD (multiple_value, multiple_value);
+#define MULTIPLE_VALUEP(x) RECORDP (x, multiple_value)
+
+#define XMULTIPLE_VALUE(x) XRECORD (x, multiple_value, multiple_value)
+#define wrap_multiple_value(p) wrap_record (p, multiple_value)
+
+#define CHECK_MULTIPLE_VALUE(x) CHECK_RECORD (x, multiple_value)
+#define CONCHECK_MULTIPLE_VALUE(x) CONCHECK_RECORD (x, multiple_value)
+
+#define multiple_value_count(x) ((x)->count)
+#define multiple_value_allocated_count(x) ((x)->allocated_count)
+#define multiple_value_first_desired(x) ((x)->first_desired)
+#define multiple_value_contents(x) ((x)->contents)
+
+#define XMULTIPLE_VALUE_COUNT(x) multiple_value_count (XMULTIPLE_VALUE (x))
+#define XMULTIPLE_VALUE_ALLOCATED_COUNT(x) \
+  multiple_value_allocated_count (XMULTIPLE_VALUE (x))
+#define XMULTIPLE_VALUE_FIRST_DESIRED(x) \
+  multiple_value_first_desired (XMULTIPLE_VALUE(x))
+#define XMULTIPLE_VALUE_CONTENTS(x) multiple_value_contents (XMULTIPLE_VALUE(x))
+
+Lisp_Object multiple_value_call (int nargs, Lisp_Object *args);
+Lisp_Object multiple_value_list_internal (int nargs, Lisp_Object *args);
+
+/* It's slightly ugly to expose this here, but it does cut down the amount
+   of work the bytecode interpreter has to do substantially. */
+extern int multiple_value_current_limit;
+
+/* Bind the multiple value limits that #'values and #'values-list pay
+   attention to. Used by bytecode and interpreted code. */
+int bind_multiple_value_limits (int first, int upper);
+
+Lisp_Object multiple_value_aref (Lisp_Object, Elemcount);
+void multiple_value_aset (Lisp_Object, Elemcount, Lisp_Object);
+
+Lisp_Object values2 (Lisp_Object first, Lisp_Object second);
+
+DECLARE_INLINE_HEADER (
+Lisp_Object 
+ignore_multiple_values (Lisp_Object obj)
+)
+{
+  return MULTIPLE_VALUEP (obj) ? multiple_value_aref (obj, 0) : obj;
+}
+
+#ifdef ERROR_CHECK_MULTIPLE_VALUES
+
+DECLARE_INLINE_HEADER (
+Lisp_Object
+ignore_multiple_values_1 (Lisp_Object obj)
+)
+{
+  if (1 == multiple_value_current_limit)
+    {
+      assert (!MULTIPLE_VALUEP (obj));
+      return obj;
+    }
+
+  return ignore_multiple_values (obj);
+}
+
+#define IGNORE_MULTIPLE_VALUES(X) ignore_multiple_values_1 (X)
+
+#else 
+#define IGNORE_MULTIPLE_VALUES(X) (multiple_value_current_limit == 1 ? (X) \
+                                   : ignore_multiple_values (X))
+#endif
+
 END_C_DECLS
 
 #endif /* INCLUDED_symeval_h_ */