New toplevel options --quit and --non-interactive
authorDavid Lichteblau <david@lichteblau.com>
Tue, 9 Aug 2011 14:45:13 +0000 (16:45 +0200)
committerDavid Lichteblau <david@lichteblau.com>
Tue, 9 Aug 2011 14:50:43 +0000 (16:50 +0200)
Implements lp#822712.

NEWS
doc/sbcl.1
src/code/toplevel.lisp
src/runtime/runtime.c
tests/toplevel.test.sh

diff --git a/NEWS b/NEWS
index 428fca9..82484cb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ changes relative to sbcl-1.0.50:
     and probe counts on Linux.
   * enhancement: building 32-bit SBCL on Linux/x86-64 now works without a
     chroot. (Use "SBCL_ARCH=x86 sh make.sh" to build.)
+  * enhancement: added new toplevel options --quit and --non-interactive
+    (lp#822712).
   * optimization: unsigned integer divisions by a constant are implemented
     using multiplication (affects CEILING, FLOOR, TRUNCATE, MOD, and REM.)
   * optimization: improved type-derivation for LOAD-TIME-VALUE.
index 7a186a4..a877657 100644 (file)
@@ -179,6 +179,17 @@ This option disables the debugger, causing errors to print a backtrace
 and exit with status 1 instead -- which is a mode of operation better suited
 for batch processing. See the User Manual on \f(CRSB\-EXT:DISABLE\-DEBUGGER\fR for details.
 .TP 3
+.B \-\-quit
+At the end of toplevel option processing, exit SBCL with a successful
+code of zero.  Note that the effect of this option is delayed until after
+toplevel options following this one.
+.TP 3
+.B \-\-non-interactive
+This option disables the read-eval-print loop for both exceptional and
+non-exceptional reasons.  It is short for --disable-debugger and --quit in
+combination and is useful for batch uses where the special option processing
+implied by --script is not desired.
+.TP 3
 .B \-\-script <filename>
 Implies \-\-no-sysinit \-\-no-userinit \-\-disable-debugger
 \-\-end\-toplevel\-options.
index 05445b9..7f71449 100644 (file)
@@ -288,7 +288,9 @@ any non-negative real number."
                (:load
                 (with-simple-restart (continue "Ignore runtime option --load ~S."
                                                value)
-                  (load (native-pathname value))))))
+                  (load (native-pathname value))))
+               (:quit
+                (quit))))
            (flush-standard-output-streams)))
     (with-simple-restart (abort "Skip rest of --eval and --load options.")
       (dolist (option options)
@@ -356,6 +358,8 @@ any non-negative real number."
         (noprint nil)
         ;; Has a --script option been seen?
         (script nil)
+        ;; Quit after processing other options?
+        (finally-quit nil)
         ;; everything in *POSIX-ARGV* except for argv[0]=programname
         (options (rest *posix-argv*)))
 
@@ -412,6 +416,16 @@ any non-negative real number."
                    ((string= option "--disable-debugger")
                     (pop-option)
                     (setf disable-debugger t))
+                   ((string= option "--quit")
+                    (pop-option)
+                    (setf finally-quit t))
+                   ((string= option "--non-interactive")
+                    ;; This option is short for --quit and --disable-debugger,
+                    ;; which are needed in combination for reliable non-
+                    ;; interactive startup.
+                    (pop-option)
+                    (setf finally-quit t)
+                    (setf disable-debugger t))
                    ((string= option "--end-toplevel-options")
                     (pop-option)
                     (return))
@@ -464,6 +478,8 @@ any non-negative real number."
               (process-init-file sysinit :system))
             (unless no-userinit
               (process-init-file userinit :user))
+            (when finally-quit
+              (push (list :quit) reversed-options))
             (process-eval/load-options (nreverse reversed-options))
             (when script
               (process-script script)
index 642e7c5..d1a215b 100644 (file)
@@ -182,6 +182,8 @@ Common toplevel options:\n\
   --disable-debugger         Invoke sb-ext:disable-debugger.\n\
   --noprint                  Run a Read-Eval Loop without printing results.\n\
   --script [<filename>]      Skip #! line, disable debugger, avoid verbosity.\n\
+  --quit                     Exit with code 0 after option processing.\n\
+  --non-interactive          Sets both --quit and --disable-debugger.\n\
 Common toplevel options that are processed in order:\n\
   --eval <form>              Form to eval when processing this option.\n\
   --load <filename>          File to load when processing this option.\n\
index 1103354..04f805e 100644 (file)
@@ -28,4 +28,50 @@ if [ "`grep -c FOO::BAR $TEST_FILESTEM`" != 1 ] ; then
     exit $EXIT_LOSE
 fi
 
+# --quit
+run_sbcl --eval "(defpackage :foo)" --eval "(print 'foo::bar)" --quit \
+    > $TEST_FILESTEM
+if [ "`grep -c FOO::BAR $TEST_FILESTEM`" != 1 ] ; then
+    echo failed DEFPACKAGE-then-PRINT with --quit
+    exit $EXIT_LOSE
+fi
+# --quit gets delayed
+run_sbcl --eval "(defpackage :foo)" --quit --eval "(print 'foo::bar)" \
+    > $TEST_FILESTEM
+if [ "`grep -c FOO::BAR $TEST_FILESTEM`" != 1 ] ; then
+    echo failed DEFPACKAGE-then-PRINT with delayed --quit
+    exit $EXIT_LOSE
+fi
+
+# --non-interactive
+run_sbcl --eval "(defpackage :foo)" \
+    --non-interactive \
+    --eval "(print 'foo::bar)" \
+    > $TEST_FILESTEM
+if [ "`grep -c FOO::BAR $TEST_FILESTEM`" != 1 ] ; then
+    echo failed DEFPACKAGE-then-PRINT with --non-interactive
+    exit $EXIT_LOSE
+fi
+
+# disable the use of --disable-debugger through run_sbcl for the rest of
+# this file
+SBCL_ARGS="--noinform --no-sysinit --no-userinit --noprint"
+
+# --non-interactive with error
+#
+# (This test would hang if --non-interactive did not work properly.)
+run_sbcl --eval "(defpackage :foo)" \
+    --non-interactive \
+    --eval "(print 'foo::bar)" \
+    --eval '(error "fail-safe")' \
+    >$TEST_FILESTEM 2>&1
+if [ "`grep -c FOO::BAR $TEST_FILESTEM`" != 1 ] ; then
+    echo failed DEFPACKAGE-then-PRINT with --non-interactive and error
+    exit $EXIT_LOSE
+fi
+if [ "`grep -c -i SIMPLE-ERROR $TEST_FILESTEM`" -lt 1 ] ; then
+    echo no error seen in --non-interactive test
+    exit $EXIT_LOSE
+fi
+
 exit $EXIT_TEST_WIN