0.9.0.13:
authorChristophe Rhodes <csr21@cam.ac.uk>
Sun, 1 May 2005 09:12:53 +0000 (09:12 +0000)
committerChristophe Rhodes <csr21@cam.ac.uk>
Sun, 1 May 2005 09:12:53 +0000 (09:12 +0000)
Miscellaneous small fixes
... manual patches, from Adam Warner and Peter Barabas
... %reader-error from Raymond Toy
... external-format tests from Teemu Kalvas

doc/manual/beyond-ansi.texinfo
doc/manual/debugger.texinfo
doc/manual/ffi.texinfo
src/code/reader.lisp
tests/external-format.impure.lisp
version.lisp-expr

index 4bb8556..61a89b8 100644 (file)
@@ -146,15 +146,15 @@ list.
 @section Efficiency Hacks
 
 The @code{sb-ext:purify} function causes SBCL first to collect all
-garbage, then to mark all uncollected objects as permanent, never
-again attempting to collect them as garbage. This can cause a large
-increase in efficiency when using a primitive garbage collector, or a
-more moderate increase in efficiency when using a more sophisticated
-garbage collector which is well suited to the program's memory usage
-pattern. It also allows permanent code to be frozen at fixed
-addresses, a precondition for using copy-on-write to share code
-between multiple Lisp processes. it is less important with modern
-generational garbage collectors.
+garbage, then to mark all uncollected objects as permanent, never again
+attempting to collect them as garbage. This can cause a large increase
+in efficiency when using a primitive garbage collector, or a more
+moderate increase in efficiency when using a more sophisticated garbage
+collector which is well suited to the program's memory usage pattern. It
+also allows permanent code to be frozen at fixed addresses, a
+precondition for using copy-on-write to share code between multiple Lisp
+processes.  This is less important with modern generational garbage
+collectors, but not all SBCL platforms use such a garbage collector.
 
 @include fun-sb-ext-purify.texinfo
 
index 7e923ed..fd299dd 100644 (file)
@@ -370,8 +370,8 @@ tail-recursively, as in this example:
 @end lisp
 
 Usually the elimination of tail-recursive frames makes debugging more
-pleasant, since theses frames are mostly uninformative.  If there is
-any doubt about how one function called another, it can usually be
+pleasant, since these frames are mostly uninformative.  If there is any
+doubt about how one function called another, it can usually be
 eliminated by finding the source location in the calling frame.
 @xref{Source Location Printing}.
 
index c8bc8d5..ea13995 100644 (file)
@@ -282,12 +282,14 @@ return zero values.
 
 @item
 The foreign type specifier @code{sb-alien:c-string} is similar to
-@code{(* char)}, but is interpreted as a null-terminated string, and
-is automatically converted into a Lisp string when accessed; or if the
+@code{(* char)}, but is interpreted as a null-terminated string, and is
+automatically converted into a Lisp string when accessed; or if the
 pointer is C @code{NULL} or @code{0}, then accessing it gives Lisp
-@code{nil}.  Lisp strings are stored with a trailing NUL
-termination, so no copying (either by the user or the implementation)
-is necessary when passing them to foreign code.
+@code{nil}.  Lisp strings of type @code{base-string} are stored with a
+trailing NUL termination, so no copying (either by the user or the
+implementation) is necessary when passing them to foreign code; strings
+of type @code{(simple-array character (*))} are copied by the
+implementation as required.
 
 Assigning a Lisp string to a @code{c-string} structure field or
 variable stores the contents of the string to the memory already
@@ -1182,8 +1184,8 @@ routine, e.g.: @samp{cc -c test.c && ld -shared -o test.so test.o} (In
 order to enable incremental loading with some linkers, you may need to
 say @samp{cc -G 0 -c test.c})
 
-Once the C code has been compiled, you can start up Lisp and load it
-in: @samp{sbcl} Lisp should start up with its normal prompt.
+Once the C code has been compiled, you can start up Lisp and load it in:
+@samp{sbcl}.  Lisp should start up with its normal prompt.
 
 Within Lisp, compile the Lisp file. (This step can be done
 separately. You don't have to recompile every time.)
index ac9ec2c..b6f28cf 100644 (file)
        (#.+char-attr-single-escape+ (go SINGLE-ESCAPE))
        (#.+char-attr-package-delimiter+ (go COLON))
        (#.+char-attr-multiple-escape+ (go MULT-ESCAPE))
-       (#.+char-attr-invalid+ (%reader-error "invalid constituent"))
+       (#.+char-attr-invalid+ (%reader-error stream "invalid constituent"))
        ;; can't have eof, whitespace, or terminating macro as first char!
        (t (go SYMBOL)))
      SIGN ; saw "sign"
index 9673578..f5a0f48 100644 (file)
   (with-open-file (s "/dev/null" :direction :input :external-format xf)
     (assert (eq (read-char s nil s) s))))
 
+;;; Test standard character read-write equivalency over all external formats.
+(let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~"))
+  (do-external-formats (xf)
+    (with-open-file (s "external-format-test.txt" :direction :output
+                    :if-exists :supersede :external-format xf)
+      (loop for character across standard-characters
+           do (write-char character s)))
+    (with-open-file (s "external-format-test.txt" :direction :input
+                    :external-format xf)
+      (loop for character across standard-characters
+           do (assert (eql (read-char s) character))))))
+
+;;; Test UTF-8 writing and reading of 1, 2, 3 and 4 octet characters with
+;;; all possible offsets. Tests for buffer edge bugs. fd-stream buffers are
+;;; 4096 wide.
+(dotimes (width-1 4)
+  (let ((character (code-char (elt '(1 #x81 #x801 #x10001) width-1))))
+    (dotimes (offset (+ width-1 1))
+      (with-open-file (s "external-format-test.txt" :direction :output
+                      :if-exists :supersede :external-format :utf-8)
+       (dotimes (n offset)
+         (write-char #\a s))
+       (dotimes (n 4097)
+         (write-char character s)))
+      (with-open-file (s "external-format-test.txt" :direction :input
+                      :external-format :utf-8)
+       (dotimes (n offset)
+         (assert (eql (read-char s) #\a)))
+       (dotimes (n 4097)
+         (assert (eql (read-char s) character)))
+       (assert (eql (read-char s nil s) s))))))
+
+;;; Test character decode restarts.
+(with-open-file (s "external-format-test.txt" :direction :output
+                :if-exists :supersede :element-type '(unsigned-byte 8))
+  (write-byte 65 s)
+  (write-byte 66 s)
+  (write-byte #xe0 s)
+  (write-byte 67 s))
+(with-open-file (s "external-format-test.txt" :direction :input
+                :external-format :utf-8)
+  (handler-bind
+      ((sb-int:character-decoding-error #'(lambda (decoding-error)
+                                           (declare (ignore decoding-error))
+                                           (invoke-restart
+                                            'sb-int:attempt-resync))))
+    (assert (equal (read-line s nil s) "ABC"))
+    (assert (equal (read-line s nil s) s))))
+(with-open-file (s "external-format-test.txt" :direction :input
+                :external-format :utf-8)
+  (handler-bind
+      ((sb-int:character-decoding-error #'(lambda (decoding-error)
+                                           (declare (ignore decoding-error))
+                                           (invoke-restart
+                                            'sb-int:force-end-of-file))))
+    (assert (equal (read-line s nil s) "AB"))
+    (assert (equal (read-line s nil s) s))))
+
+;;; Test character encode restarts.
+(with-open-file (s "external-format-test.txt" :direction :output
+                :if-exists :supersede :external-format :latin-1)
+  (handler-bind
+      ((sb-int:character-encoding-error #'(lambda (encoding-error)
+                                           (declare (ignore encoding-error))
+                                           (invoke-restart
+                                            'sb-impl::output-nothing))))
+    (write-char #\A s)
+    (write-char #\B s)
+    (write-char (code-char 322) s)
+    (write-char #\C s)))
+(with-open-file (s "external-format-test.txt" :direction :input
+                :external-format :latin-1)
+  (assert (equal (read-line s nil s) "ABC"))
+  (assert (equal (read-line s nil s) s)))
+
+(with-open-file (s "external-format-test.txt" :direction :output
+                :if-exists :supersede :external-format :latin-1)
+  (handler-bind
+      ((sb-int:character-encoding-error #'(lambda (encoding-error)
+                                           (declare (ignore encoding-error))
+                                           (invoke-restart
+                                            'sb-impl::output-nothing))))
+    (let ((string (make-array 4 :element-type 'character
+                             :initial-contents `(#\A #\B ,(code-char 322)
+                                                     #\C))))
+      (write-string string s))))
+(with-open-file (s "external-format-test.txt" :direction :input
+                :external-format :latin-1)
+  (assert (equal (read-line s nil s) "ABC"))
+  (assert (equal (read-line s nil s) s)))
+
+;;; Test skipping character-decode-errors in comments.
 (let ((s (open "external-format-test.lisp" :direction :output
               :if-exists :supersede :external-format :latin-1)))
   (unwind-protect
        (delete-file p)))))
 
 (sb-ext:quit :unix-status 104)
-    
\ No newline at end of file
index 462e001..8965216 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.0.12"
+"0.9.0.13"