0.pre8.58:
authorWilliam Harold Newman <william.newman@airmail.net>
Mon, 14 Apr 2003 01:42:14 +0000 (01:42 +0000)
committerWilliam Harold Newman <william.newman@airmail.net>
Mon, 14 Apr 2003 01:42:14 +0000 (01:42 +0000)
Do EVAL of one --eval form before READ of the next --eval form.
(to avoid package gotchas reported by dan_b)

NEWS
doc/sbcl.1
src/code/toplevel.lisp
tests/toplevel.sh [new file with mode: 0644]
version.lisp-expr

diff --git a/NEWS b/NEWS
index 6fca07c..38017d6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1613,8 +1613,8 @@ changes in sbcl-0.7.14 relative to sbcl-0.7.13:
 
 changes in sbcl-0.8.0 relative to sbcl-0.7.14
   * The old distinction between CL:CLASS objects and SB-PCL:CLASS
-    objects has been removed.  The return value from CL:FIND-CLASS is
-    now a CLOS class, and likewise that of CL:CLASS-OF;
+    objects has been eliminated.  The return value from CL:FIND-CLASS
+    is now a CLOS class, and likewise that of CL:CLASS-OF;
     CL:BUILT-IN-CLASS, CL:STRUCTURE-CLASS and CL:STANDARD-CLASS name
     CLOS classes.
   * An interface to the MetaObject Protocol, as described in Kiczales,
@@ -1628,6 +1628,12 @@ changes in sbcl-0.8.0 relative to sbcl-0.7.14
     addresses instead of being hardcoded per-port.  Users affected by
     this probably have to be doing advanced things with shared
     libraries, and will know who they are.
+  * minor incompatible change: Previously, all --eval forms used were
+    processed with READ before any of them were processed with EVAL.
+    Now each --eval form is processed with both READ and EVAL before
+    the next --eval form is processed. (Thus package operations like
+    sbcl --eval "(defpackage :foo)" --eval "(print 'foo::bar)" now work
+    as the user might reasonably expect.)
   * minor incompatible change: *STANDARD-INPUT* is now only an
     INPUT-STREAM, not a BIDIRECTIONAL-STREAM. (thanks to Antonio 
     Martinez)
index d7093b1..98204ae 100644 (file)
@@ -309,9 +309,9 @@ initialization file to be read, but on a Unix system "--userinit
 .TP 3
 .B --eval <command>
 After executing any initialization file, but before starting the
-read-eval-print loop on standard input, evaluate the command given.
-More than one --eval option can be used, and all will be executed, in
-the order they appear on the command line.
+read-eval-print loop on standard input, read and evaluate the command
+given. More than one --eval option can be used, and all will be read
+and executed, in the order they appear on the command line.
 .TP 3
 .B --load <filename>
 This is equivalent to --eval '(load "<filename>")'. The special
@@ -344,10 +344,10 @@ command.)
 Regardless of the order in which --sysinit, --userinit, and --eval
 options appear on the command line, the sysinit file, if it exists, is
 loaded first; then the userinit file, if it exists, is loaded; then
-any --eval commands are executed in sequence; then the read-eval-print
-loop is started on standard input. At any step, error conditions or
-commands such as SB-EXT:QUIT can cause execution to be terminated
-before proceeding to subsequent steps.
+any --eval commands are read and executed in sequence; then the
+read-eval-print loop is started on standard input. At any step, error
+conditions or commands such as SB-EXT:QUIT can cause execution to be
+terminated before proceeding to subsequent steps.
 
 Note that when running SBCL with the --core option, using a core file
 created by a user call to the SB-EXT:SAVE-LISP-AND-DIE, the toplevel
index d779e57..f245850 100644 (file)
   (/show0 "entering TOPLEVEL-INIT")
   (setf sb!thread::*session-lock* (sb!thread:make-mutex :name "the terminal"))
   (sb!thread::get-foreground)
-  (let ((sysinit nil)        ; value of --sysinit option
-       (userinit nil)       ; value of --userinit option
-       (reversed-evals nil) ; values of --eval options, in reverse order; and
-                            ; also --load options, translated into --eval
-       (noprint nil)        ; Has a --noprint option been seen?
-       (options (rest *posix-argv*))) ; skipping program name
+  (let (;; value of --sysinit option
+       (sysinit nil)
+       ;; value of --userinit option
+       (userinit nil)
+       ;; values of --eval options, in reverse order; and also any
+       ;; other options (like --load) which're translated into --eval
+       ;;
+       ;; The values are stored as strings, so that they can be
+       ;; passed to READ only after their predecessors have been
+       ;; EVALed, so that things work when e.g. REQUIRE in one EVAL
+       ;; form creates a package referred to in the next EVAL form.
+       (reversed-evals nil) 
+       ;; Has a --noprint option been seen?
+       (noprint nil)        
+       ;; everything in *POSIX-ARGV* except for argv[0]=programname
+       (options (rest *posix-argv*))) 
 
     (declare (type list options))
 
                         (setf userinit (pop-option))))
                    ((string= option "--eval")
                     (pop-option)
-                    (let ((eval-as-string (pop-option)))
-                      (with-input-from-string (eval-stream eval-as-string)
-                        (let* ((eof-marker (cons :eof :eof))
-                               (eval (read eval-stream nil eof-marker))
-                               (eof (read eval-stream nil eof-marker)))
-                          (cond ((eq eval eof-marker)
-                                 (error "unable to parse ~S"
-                                        eval-as-string))
-                                ((not (eq eof eof-marker))
-                                 (error "more than one expression in ~S"
-                                        eval-as-string))
-                                (t
-                                 (push eval reversed-evals)))))))
+                    (push (pop-option) reversed-evals))
                    ((string= option "--load")
                     (pop-option)
-                    (push `(load ,(pop-option)) reversed-evals))
+                    (push (concatenate 'string "(LOAD \"" (pop-option) "\")")
+                          reversed-evals))
                    ((string= option "--noprint")
                     (pop-option)
                     (setf noprint t))
                    ((string= option "--noprogrammer")
                     (warn "treating deprecated --noprogrammer as --disable-debugger")
                     (pop-option)
-                    (push '(disable-debugger) reversed-evals))
+                    (push "(DISABLE-DEBUGGER)" reversed-evals))
                    ((string= option "--disable-debugger")
                     (pop-option)
-                    (push '(disable-debugger) reversed-evals))
+                    (push "(DISABLE-DEBUGGER)" reversed-evals))
                    ((string= option "--end-toplevel-options")
                     (pop-option)
                     (return))
                         (return)))))))
     (/show0 "done with LOOP WHILE OPTIONS DO in TOPLEVEL-INIT")
 
-    ;; Excise all the options that we processed, so that only
+    ;; Delete all the options that we processed, so that only
     ;; user-level options are left visible to user code.
     (setf (rest *posix-argv*) options)
 
 
              ;; Process --eval options.
              (/show0 "handling --eval options in TOPLEVEL-INIT")
-             (dolist (eval (reverse reversed-evals))
+             (dolist (expr-as-string (reverse reversed-evals))
                (/show0 "handling one --eval option in TOPLEVEL-INIT")
-               (eval eval)
-               (flush-standard-output-streams)))
+               (let ((expr (with-input-from-string (eval-stream
+                                                    expr-as-string)
+                             (let* ((eof-marker (cons :eof :eof))
+                                    (result (read eval-stream nil eof-marker))
+                                    (eof (read eval-stream nil eof-marker)))
+                               (cond ((eq result eof-marker)
+                                      (error "unable to parse ~S"
+                                             expr-as-string))
+                                     ((not (eq eof eof-marker))
+                                      (error "more than one expression in ~S"
+                                             expr-as-string))
+                                     (t
+                                      result))))))
+                 (eval expr)
+                 (flush-standard-output-streams))))
          (continue ()
            :report
            "Continue anyway (skipping to toplevel read/eval/print loop)."
diff --git a/tests/toplevel.sh b/tests/toplevel.sh
new file mode 100644 (file)
index 0000000..c089c04
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# tests related to the toplevel interface: command line parsing
+# and outer REPL
+
+# This software is part of the SBCL system. See the README file for
+# more information.
+#
+# While most of SBCL is derived from the CMU CL system, the test
+# files (like this one) were written from scratch after the fork
+# from CMU CL.
+# 
+# This software is in the public domain and is provided with
+# absolutely no warranty. See the COPYING and CREDITS files for
+# more information.
+
+testfile=${TMPDIR:-/tmp}/sbcl-toplevel-test-$$.tmp
+
+# Until sbcl-0.pre8, all --eval arguments were parsed before any of
+# them were executed, making it impossible for --eval forms to refer
+# to packages created by --eval forms.
+${SBCL:-sbcl} --eval "(defpackage :foo)" --eval "(print 'foo::bar)" \
+  < /dev/null > $testfile
+if [ "`grep -c FOO::BAR $testfile`" != 1 ] ; then
+    echo failed DEFPACKAGE-then-PRINT from --eval form
+    exit 1
+fi
index 97fe437..432773c 100644 (file)
@@ -18,4 +18,4 @@
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
 
-"0.pre8.57"
+"0.pre8.58"