From 7b5628003e3016985952908016219b872ed48811 Mon Sep 17 00:00:00 2001 From: Christophe Rhodes Date: Sun, 1 May 2005 09:12:53 +0000 Subject: [PATCH] 0.9.0.13: 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 | 18 +++---- doc/manual/debugger.texinfo | 4 +- doc/manual/ffi.texinfo | 16 ++++--- src/code/reader.lisp | 2 +- tests/external-format.impure.lisp | 93 ++++++++++++++++++++++++++++++++++++- version.lisp-expr | 2 +- 6 files changed, 114 insertions(+), 21 deletions(-) diff --git a/doc/manual/beyond-ansi.texinfo b/doc/manual/beyond-ansi.texinfo index 4bb8556..61a89b8 100644 --- a/doc/manual/beyond-ansi.texinfo +++ b/doc/manual/beyond-ansi.texinfo @@ -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 diff --git a/doc/manual/debugger.texinfo b/doc/manual/debugger.texinfo index 7e923ed..fd299dd 100644 --- a/doc/manual/debugger.texinfo +++ b/doc/manual/debugger.texinfo @@ -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}. diff --git a/doc/manual/ffi.texinfo b/doc/manual/ffi.texinfo index c8bc8d5..ea13995 100644 --- a/doc/manual/ffi.texinfo +++ b/doc/manual/ffi.texinfo @@ -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.) diff --git a/src/code/reader.lisp b/src/code/reader.lisp index ac9ec2c..b6f28cf 100644 --- a/src/code/reader.lisp +++ b/src/code/reader.lisp @@ -832,7 +832,7 @@ (#.+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" diff --git a/tests/external-format.impure.lisp b/tests/external-format.impure.lisp index 9673578..f5a0f48 100644 --- a/tests/external-format.impure.lisp +++ b/tests/external-format.impure.lisp @@ -25,6 +25,98 @@ (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 @@ -40,4 +132,3 @@ (delete-file p))))) (sb-ext:quit :unix-status 104) - \ No newline at end of file diff --git a/version.lisp-expr b/version.lisp-expr index 462e001..8965216 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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" -- 1.7.10.4