diff --git a/src/code/commandline.lisp b/src/code/commandline.lisp
index 36f037a015512ffd1c874e8a94ff16c648f9f677..be67ddcd718d3a6da468d234898a81e7145c669b 100644
--- a/src/code/commandline.lisp
+++ b/src/code/commandline.lisp
@@ -72,7 +72,7 @@
 
 ;;;; Processing the command strings.
 
-(defun process-command-strings ()
+(defun process-command-strings (init-command-switches-p)
   (setq *command-line-words* nil)
   (setq *command-line-switches* nil)
   (let ((cmd-strings lisp::lisp-command-line-list)
@@ -103,7 +103,7 @@
       (return-from process-command-strings nil))
     
     ;; Set command line switches.
-    ;; 
+    ;;
     (loop
       (unless str
 	(return (setf *command-line-switches*
@@ -119,14 +119,16 @@
 	(let (word-list)
 	  (loop
 	    (unless str
-	      (push (make-cmd-switch switch value (nreverse word-list))
-		    *command-line-switches*)
+	      (when init-command-switches-p
+		(push (make-cmd-switch switch value (nreverse word-list))
+		      *command-line-switches*))
 	      (return nil))
 	    
 	    (unless (zerop (length (the simple-string str)))
 	      (when (char= #\- (schar str 0))
-		(push (make-cmd-switch switch value (nreverse word-list))
-		      *command-line-switches*)
+		(when init-command-switches-p
+		  (push (make-cmd-switch switch value (nreverse word-list))
+			*command-line-switches*))
 		(when (and (= (length str) 2)
 			   (char= #\- (schar str 1)))
 		  ;; Gather up everything after --, and exit.
@@ -134,7 +136,7 @@
 		  (setf str nil))
 		(return nil))
 	      (push str word-list))
-	    (setq str (pop cmd-strings))))))))
+	    (setq str (pop cmd-strings)))))))))
 
 (defun get-command-line-switch (sname)
   "Accepts the name of a switch as a string and returns the value of
diff --git a/src/code/describe.lisp b/src/code/describe.lisp
index b1bd93f8cbecc6f927e935198eadc63f6c532f05..3616b3616560e90fd7505273f1309a06b9c6f665 100644
--- a/src/code/describe.lisp
+++ b/src/code/describe.lisp
@@ -313,11 +313,12 @@
   (let ((info (kernel:%code-debug-info code-obj)))
     (when info
       (let ((sources (c::debug-info-source info)))
-	(format t (intl:gettext "~&On ~A it was compiled from:")
-		(format-universal-time nil
-				       (c::debug-source-compiled
-					(first sources))
-				       :style :iso8601))
+	(when sources
+	  (format t (intl:gettext "~&On ~A it was compiled from:")
+		  (format-universal-time nil
+					 (c::debug-source-compiled
+					  (first sources))
+					 :style :iso8601)))
 	(dolist (source sources)
 	  (let ((name (c::debug-source-name source)))
 	    (ecase (c::debug-source-from source)
diff --git a/src/code/save.lisp b/src/code/save.lisp
index 11450d0bb0e8216718a288e382ed000080f5fe8b..696d79e7a3d4bc88006d3c98bc730a4539032e86 100644
--- a/src/code/save.lisp
+++ b/src/code/save.lisp
@@ -153,7 +153,8 @@
 				 (process-command-line t)
 		                  #+:executable
 		                 (executable nil)
-				 (batch-mode nil))
+				 (batch-mode nil)
+				 (quiet nil))
   "Saves a CMU Common Lisp core image in the file of the specified name.  The
   following keywords are defined:
   
@@ -191,8 +192,10 @@
 
   :process-command-line
       If true (the default), process command-line switches via the normal
-  mechanisms, otherwise ignore all switches (except those processed by the
-  C startup code).
+  mechanisms, otherwise ignore all switches (except those processed by
+  the C startup code).  In either case, the command line switches are
+  saved in *COMMAND-LINE-STRINGS* and
+  *COMMAND-LINE-APPLICATION-ARGUMENTS*.
 
   :executable
       If nil (the default), save-lisp will save using the traditional
@@ -203,7 +206,14 @@
   :batch-mode
       If nil (the default), then the presence of the -batch command-line
   switch will invoke batch-mode processing.  If true, the produced core
-  will always be in batch-mode, regardless of any command-line switches."
+  will always be in batch-mode, regardless of any command-line switches.
+
+  :quiet
+     If non-NIL, loading, compiling, and GC messages are suppressed.
+     This is equivalent to setting *load-verbose*, *compile-verbose*,
+     *compile-print*, *compile-progress*, *require-verbose*, and
+     *gc-verbose* all to NIL.  If NIL (the default), the default
+     values of these variables are used."
 
   (unless (probe-file (directory-namestring core-file-name))
     (error 'simple-file-error
@@ -240,8 +250,7 @@
 	     (environment-init)
 	     (dolist (f *after-save-initializations*) (funcall f))
 	     (intl::setlocale)
-	     (when process-command-line
-	       (ext::process-command-strings))
+	     (ext::process-command-strings process-command-line)
 	     (setf *editor-lisp-p* nil)
 	     (macrolet ((find-switch (name)
 			  `(find ,name *command-line-switches*
@@ -249,7 +258,8 @@
 				 :test #'(lambda (x y)
 					   (declare (simple-string x y))
 					   (string-equal x y)))))
-               (when (and process-command-line (find-switch "quiet"))
+               (when (or quiet
+			 (and process-command-line (find-switch "quiet")))
                  (setq *load-verbose* nil
                        *compile-verbose* nil
                        *compile-print* nil
@@ -285,8 +295,9 @@
 		 (ext::invoke-switch-demons *command-line-switches*
 					    *command-switch-demons*))
 	       (when (and print-herald
-			  (not (and process-command-line
-				    (find-switch "quiet"))))
+			  (not (or quiet
+				   (and process-command-line
+					(find-switch "quiet")))))
 		 ;; Don't print the herald if -quiet is given.
 		 (print-herald)))))
 	 (funcall init-function))
diff --git a/src/compiler/main.lisp b/src/compiler/main.lisp
index 5c5386dd829b723f16ade88b3ea975061008564a..8a5d92d85c4dd69df848ceb39ef27723c8b4120f 100644
--- a/src/compiler/main.lisp
+++ b/src/compiler/main.lisp
@@ -2041,11 +2041,7 @@
 		     ((or cons eval:interpreted-function)
 		      `#',(get-lambda-to-compile definition))
 		     (function
-		      (multiple-value-bind (exp lexenv)
-			  (function-lambda-expression definition)
-			(if (and exp (not lexenv))
-			    `#',exp
-			    `',definition)))))
+		      definition)))
 	     (*source-info* (make-lisp-source-info form))
 	     (*top-level-lambdas* ())
 	     (*converting-for-interpreter* nil)
@@ -2069,6 +2065,14 @@
 	     (*gensym-counter* 0)
 	     (*current-function-names* (list name))
 	     (intl::*default-domain* intl::*default-domain*))
+	;; As mentioned above, we can return the same function if the
+	;; function was already compiled.  We do this when FORM is EQ
+	;; to DEFINITION (which happens above if we have a compiled
+	;; function that we don't have the source for or was defined
+	;; in a non-null environment.
+	(when (and name (eq form definition))
+	  (return-from compile
+	    (values name nil nil)))
 	(with-debug-counters
 	  (clear-stuff)
 	  (find-source-paths form 0)
diff --git a/src/docs/cmu-user/cmu-user.tex b/src/docs/cmu-user/cmu-user.tex
index ee7eae031205c011626e274d04be70158b355a6c..42654aba0136222269e3c718409a99f59e9c2e1f 100644
--- a/src/docs/cmu-user/cmu-user.tex
+++ b/src/docs/cmu-user/cmu-user.tex
@@ -48,7 +48,7 @@
 \newcommand{\keywords}{lisp, Common Lisp, manual, compiler, programming
 language implementation, programming environment}
 
-\date{October 2014 \\ 20f}
+\date{October 2016 \\ 21b}
 
 
 \begin{document}
diff --git a/src/docs/cmu-user/extensions.tex b/src/docs/cmu-user/extensions.tex
index 839ce5d6fee4f0fedc8a8e5054c0e4673dab7db8..b5bbfff251abf74288129f5caa1a54b4e50e486b 100644
--- a/src/docs/cmu-user/extensions.tex
+++ b/src/docs/cmu-user/extensions.tex
@@ -1099,7 +1099,8 @@ It is possible to run programs from Lisp by using the following function.
       \morekeys{\kwd{if-input-does-not-exist}}
       \yetmorekeys{\kwd{output} \kwd{if-output-exists}}
       \yetmorekeys{\kwd{error} \kwd{if-error-exists}}
-      \yetmorekeys{\kwd{status-hook} \kwd{before-execve}}}}
+      \yetmorekeys{\kwd{status-hook} \kwd{external-format}}
+      \yetmorekeys{\kwd{element-type}}}}
      
   \code{run-program} runs \var{program} in a child process.
   \var{Program} should be a pathname or string naming the program.
@@ -1154,6 +1155,11 @@ It is possible to run programs from Lisp by using the following function.
     already contains all the input for the process.  In this case
     \code{run-program} reads all the input from this stream before
     returning, so this cannot be used to interact with the process.
+    If \kwd{input} is a string stream, it is up to the caller to call
+    \code{string-encode} or other function to convert the string to
+    the appropriate encoding.  In either case, the least significant 8
+    bits of the \code{char-code} of each \code{character} is
+    sent to the program.
     
   \item[\kwd{if-input-does-not-exist}] This specifies what to do if
     the input file does not exist.  The following values are valid:
@@ -1172,7 +1178,10 @@ It is possible to run programs from Lisp by using the following function.
     \code{process-output} slot contains an input stream from which you
     can read the program's output.  \kwd{output} can also be a stream
     in which case all output from the process is written to this
-    stream. 
+    stream.  If \kwd{output} is a string-stream, each octet read from
+    the program is converted to a character using \code{code-char}.
+    It is up to the caller to convert this using the appropriate
+    external format to create the desired encoded string.
     
   \item[\kwd{if-output-exists}] This specifies what to do if the
     output file already exists.  The following values are valid:
@@ -1197,6 +1206,15 @@ It is possible to run programs from Lisp by using the following function.
     the process changes status.  This is especially useful when
     specifying \kwd{wait} as \nil.  The function takes the process as
     a required argument.
+
+  \item[\kwd{external-format}] This specifies the external format to
+    use for streams created for \code{run-program}.  This does not
+    apply to string streams passed in as \kwd{input} or \kwd{output}
+    parameters.
+
+  \item[\kwd{element-type}] If streams are created \code{run-program},
+    use this as the \kwd{element-type} for the stream.  Defaults to
+    \code{BASE-CHAR}. 
     
 %   \item[\kwd{before-execve}] This specifies a function to run in the
 %     child process before it becomes the program to run.  This is
diff --git a/src/general-info/release-21b.txt b/src/general-info/release-21b.txt
index 44ab2215253dff0d9a83e1512d22f862ed4d8ae7..9c3ba2da6c642d2a595e420943ae106d7da48f4c 100644
--- a/src/general-info/release-21b.txt
+++ b/src/general-info/release-21b.txt
@@ -48,7 +48,7 @@ New in this release:
       WITH-FLOAT-TRAPS-MASKED.
     * (EXPT 0 power) doesn't throw INTEXP-LIMIT-ERROR anymore for any
       integer value of power.
-    * Starting cmucl with "-dyanmic-space-size 0" means using the
+    * Starting cmucl with "-dynamic-space-size 0" means using the
       maximum possible heap size for the platform.
     * More descriptive docstring for
       * *environment-list*
@@ -56,16 +56,21 @@ New in this release:
     * Maximum dynamic-space-size on Linux reduced to 1530 MB because
       that's the largest available space on 32-bit Ubuntu 11.10.
     * For linux, darwin, and solaris/sparc, the binding stack and
-      control stack are now mapped into memory whereever the OS wishes
+      control stack are now mapped into memory wherever the OS wishes
       to place them instead of being mapped into a fixed location.
       This is indicated by new feature :relocatable-stacks.
 
   * ANSI compliance fixes:
     * PATHNAME-MATCH-P did not accept search-lists.
+    * (compile 'foo) returns the compiled function if foo is already
+      compiled. (See Ticket #24).  This is a change in behavior for
+      developers where foo would be recompiled if the source was
+      available.  Developers might want to investigate uncompile
+      combined with compile to get the old behavior back.
 
-  * Bugfixes:
+  * Bug fixes:
     * Linux was missing unix-setitimer which prevented saving cores.
-    * Generate inxact exceptions more carefully.
+    * Generate inexact exceptions more carefully.
     * Fix FP issue when building with Xcode 7.2 (and newer versions of
       clang).  (See ticket #12.)
     * Cleanups in handling floating-point exceptions.  See Tickets #15
@@ -94,8 +99,13 @@ New in this release:
     * Ticket #27 fixed: Regression: ASDF test failures
     * Ticket #28 fixed: Recursive function definition during
       cross-compile
+    * Ticket #30 fixed: Compilation of (describe 'foo)
+    * Ticket #31 fixed: (compile #'foo) fails
+    * Ticket #24 fixed: Compilation of (compile 'foo)
+    * Ticket #32 fixed: doc fix: ext:run-program has no before-execve option
 
   * Other changes:
+    * Update user manual.
 
   * Improvements to the PCL implementation of CLOS:
 
diff --git a/src/i18n/locale/cmucl.pot b/src/i18n/locale/cmucl.pot
index 5cdda5309bb89201971b17e3931c00fa2a17070f..7847d729e565a9bf5b02e9b2d6cc07f4c7b0e45d 100644
--- a/src/i18n/locale/cmucl.pot
+++ b/src/i18n/locale/cmucl.pot
@@ -6713,8 +6713,10 @@ msgid ""
 "\n"
 "  :process-command-line\n"
 "      If true (the default), process command-line switches via the normal\n"
-"  mechanisms, otherwise ignore all switches (except those processed by the\n"
-"  C startup code).\n"
+"  mechanisms, otherwise ignore all switches (except those processed by\n"
+"  the C startup code).  In either case, the command line switches are\n"
+"  saved in *COMMAND-LINE-STRINGS* and\n"
+"  *COMMAND-LINE-APPLICATION-ARGUMENTS*.\n"
 "\n"
 "  :executable\n"
 "      If nil (the default), save-lisp will save using the traditional\n"
@@ -6725,7 +6727,14 @@ msgid ""
 "  :batch-mode\n"
 "      If nil (the default), then the presence of the -batch command-line\n"
 "  switch will invoke batch-mode processing.  If true, the produced core\n"
-"  will always be in batch-mode, regardless of any command-line switches."
+"  will always be in batch-mode, regardless of any command-line switches.\n"
+"\n"
+"  :quiet\n"
+"     If non-NIL, loading, compiling, and GC messages are suppressed.\n"
+"     This is equivalent to setting *load-verbose*, *compile-verbose*,\n"
+"     *compile-print*, *compile-progress*, *require-verbose*, and\n"
+"     *gc-verbose* all to NIL.  If NIL (the default), the default\n"
+"     values of these variables are used."
 msgstr ""
 
 #: src/code/save.lisp
diff --git a/tests/issues.lisp b/tests/issues.lisp
index b02fc1266886d13ed1a6771d2f3fe786274ae9ba..d709a71910c4cae2e5aeca42c6ac2e950dc1c1fb 100644
--- a/tests/issues.lisp
+++ b/tests/issues.lisp
@@ -298,3 +298,26 @@
 	(assert-eql (length in-string) (length out-string))
 	(assert-equal in-string out-string)))))
 
+
+
+(define-test issue.30
+    (:tag :issues)
+  (let* ((test-file #.(merge-pathnames #p"resources/issue-30.lisp" cl:*load-pathname*))
+	 (fasl-file (compile-file-pathname test-file)))
+    ;; Compiling and loading the test file should succeed without
+    ;; errors.
+    (assert-true (pathnamep test-file))
+    (assert-true (pathnamep fasl-file))
+    (assert-equalp (list fasl-file nil nil)
+		  (multiple-value-list (compile-file test-file :load t)))))
+
+(define-test issue.24
+    (:tag :issues)
+  (let* ((test-file #.(merge-pathnames #p"resources/issue-24.lisp" cl:*load-pathname*)))
+    (assert-true (compile-file test-file :load t))))
+
+(define-test issue.32
+    (:tag :issues)
+  (assert-error 'kernel:simple-program-error
+		(ext:run-program "cat" nil
+				 :before-execve t)))
diff --git a/tests/resources/issue-30.lisp b/tests/resources/issue-30.lisp
new file mode 100644
index 0000000000000000000000000000000000000000..d924295797b9d8062458a5bce9b49d63f3de5d3a
--- /dev/null
+++ b/tests/resources/issue-30.lisp
@@ -0,0 +1,4 @@
+(defun foo ()
+  (print "Hello world"))
+
+(describe 'foo)