Rightest one attached here - using (char-code *substitution-char*) instead of *substitution-char* itself.
Sorry again, -Anton
Anton Vodonosov:
Sorry, patch in previouse message contains few copy-pasted lines that I forgot to remove. Right version is attached.
-Anton
Anton Vodonosov:
Hi!
Edi, what do you think about following refactoring.
Remove *provide-use-value-restart* variable, but save performance.
To avoid verbose description, I've attached a patch. It is only a sketch of how it can be done, I event haven't compiled it.
Thus public interface of the library may be simplified, at the cost of more complex responsibilities of char-readers defined using define-char-reader macro: they should use recover-from-encoding-error.
By the way. May be define-char-code-reader is more accurate name for the macro than define-cahr-reader
Regards, -Anton
--- input.lisp 2007-02-24 23:36:16.237125400 +0200 +++ input+.lisp 2007-02-25 00:48:08.718168600 +0200 @@ -150,52 +150,50 @@ (last-char-code flexi-stream-last-char-code)) ,stream-var ;; set LAST-OCTET slot to NIL because we can't UNREAD-BYTE after ;; this operation (setq last-octet nil) (let ((,char-code (flet ((,body-fn () ,@body)) (declare (inline ,body-fn) (dynamic-extent (function ,body-fn))) - (cond (*provide-use-value-restart* - (restart-case - (handler-bind ((flexi-stream-encoding-error - (lambda (condition) - (declare (ignore condition)) - (when *substitution-char* - (use-value *substitution-char*))))) - (,body-fn)) - (use-value (,char) - :report "Specify a character to be used instead." - :interactive (lambda () - (loop - (format *query-io* "Type a character: ") - (let ((,line (read-line *query-io*))) - (when (= 1 (length ,line)) - (return (list (char ,line 0))))))) - (char-code ,char)))) - (t (,body-fn)))))) + (,body-fn)))) (when (eq ,char-code :eof) (return-from stream-read-char :eof)) ;; remember this character and the current external format ;; for UNREAD-CHAR (setq last-char-code ,char-code) (or (code-char ,char-code) ,char-code))))))
(define-char-reader (stream flexi-latin-1-input-stream) (or (read-byte* stream) (return-from stream-read-char :eof)))
(define-char-reader (stream flexi-ascii-input-stream) (let ((octet (or (read-byte* stream) (return-from stream-read-char :eof)))) (declare (type octet octet)) - (when (> octet 127) - (signal-encoding-error stream "No character which corresponds to octet #x~X." octet)) - octet)) + (if (> octet 127) + (recover-from-encoding-error stream "No character which corresponds to octet #x~X." octet) + octet))) + +(defun recover-from-encoding-error (flexi-stream format-control &rest format-args) + (if *substitution-char* + (char-code *substitution-char*) + (restart-case + (apply #'signal-encoding-error `(flexi-stream fromat-control @,format-args)) + (use-value (,char) + :report "Specify a character to be used instead." + :interactive (lambda () + (loop + (format *query-io* "Type a character: ") + (let ((,line (read-line *query-io*))) + (when (= 1 (length ,line)) + (return (list (char ,line 0))))))) + (char-code ,char))))
(define-char-reader (stream flexi-8-bit-input-stream) (with-accessors ((encoding-table flexi-stream-encoding-table)) stream (let* ((octet (or (read-byte* stream) (return-from stream-read-char :eof))) (char-code (aref (the (simple-array * *) encoding-table) octet))) (declare (type octet octet))