anchor.diff:                     (ib input-buffer-of)
                      (ef external-format-of))
         stream
  -    (let ((str nil)
  -          (ret nil)
  -          (eof nil))
  -      (block nil
  -        ;; BUG: this comparision is probably buggy, FIXME.  A similar
  -        ;; bug was fixed in STREAM-READ-CHAR.  Must write a test for
  -        ;; this one first.
  -        (when (< 0 (iobuf-end-space-length ib) 4)
  -          (iobuf-copy-data-to-start ib))
  -        (when (and (iomux:fd-ready-p fd :input)
  -                   (eq :eof (%fill-ibuf read-fn fd ib)))
  -          (setf eof t))
  -        (when (zerop (iobuf-length ib))
  -          (return (if eof :eof nil)))
  -        ;; line-end handling
  -        (let ((line-end (maybe-find-line-ending-no-hang fd ib ef)))
  -          (cond ((eq line-end :starvation)
  -                 (return (if eof #\Return nil)))
  -                ((characterp line-end)
  -                 (return line-end))))
  -        ;; octet decoding
  -        (handler-case
  -            (setf (values str ret)
  -                  (foreign-string-to-lisp
  -                   (iobuf-data ib)
  -                   :offset (iobuf-start ib)
  -                   :count (iobuf-length ib)
  -                   :encoding (babel:external-format-encoding ef)
  -                   :max-chars 1))
  -          (babel:end-of-input-in-character ()
  -            (return nil)))
  -        (incf (iobuf-start ib) ret)
  -        (char str 0)))))
  +    (let* ((str nil) (ret nil) (eof nil)
  +           (encoding (babel:external-format-encoding ef))
  +           (max-octets-per-char
  +            (babel-encodings:enc-max-units-per-char encoding)))
  +      ;; BUG: this comparision is probably buggy, FIXME.  A similar
  +      ;; bug was fixed in STREAM-READ-CHAR.  Must write a test for
  +      ;; this one first.
  +      (when (< (- (iobuf-size ib)
  +                  (iobuf-start ib))
  +               max-octets-per-char)
  +        (iobuf-copy-data-to-start ib))
  +      (when (and (iomux:fd-ready-p fd :input)
  +                 (eq :eof (%fill-ibuf read-fn fd ib)))
  +        (setf eof t))
  +      (when (zerop (iobuf-length ib))
  +        (return* (if eof :eof nil)))
  +      ;; line-end handling
  +      (let ((line-end (maybe-find-line-ending-no-hang fd ib ef)))
  +        (cond ((eq :starvation line-end)
  +               (return* (if eof #\Return nil)))
  +              ((characterp line-end)
  +               (return* line-end))))
  +      ;; octet decoding
  +      (handler-case
  +          (setf (values str ret)
  +                (foreign-string-to-lisp
  +                 (iobuf-data ib)
  +                 :offset (iobuf-start ib)
  +                 :count (iobuf-length ib)
  +                 :encoding encoding
  +                 :max-chars 1))
  +        (babel:end-of-input-in-character ()
  +          (return* nil)))
  +      (incf (iobuf-start ib) ret)
  +      (char str 0))))
   
   (defun %stream-unread-char (stream)
     (declare (type dual-channel-gray-stream stream))
  
positive.code:               ;; Some encodings such as CESU or Java's modified UTF-8 take
                ;; as much as 6 bytes per character. Make sure we have enough
                ;; space to collect read-ahead bytes if required.
                ((< (iobuf-length ib) +max-octets-per-char+)
                 (iobuf-copy-data-to-start ib)
                 (setf unread-index 0)))
          ;; line-end handling
  
negative.code:     (iobuf-reset ib)
      nil))
  
  (defun %fill-ibuf (read-fn fd buf)
    (let ((num (nix:repeat-upon-eintr
                 (funcall read-fn fd (iobuf-end-pointer buf)
                          (iobuf-end-space-length buf)))))
  