3 ;;; **********************************************************************
4 ;;; This code was written by Paul Foley and has been placed in the public
8 ;;; Sbcl port by Rudi Schlatte.
10 (in-package "SB-SIMPLE-STREAMS")
13 ;;; **********************************************************************
15 ;;; Strategy functions for base simple-stream classes
19 (defun refill-buffer (stream blocking)
20 (declare (type blocking blocking))
21 (with-stream-class (simple-stream stream)
22 (let* ((unread (sm last-char-read-size stream))
23 (buffer (sm buffer stream))
24 (bufptr (sm buffer-ptr stream)))
25 (unless (or (zerop unread) (zerop bufptr))
26 (buffer-copy buffer (- bufptr unread) buffer 0 unread))
27 (let ((bytes (device-read stream nil unread nil blocking)))
28 (declare (type fixnum bytes))
29 (setf (sm buffpos stream) unread
30 (sm buffer-ptr stream) (if (plusp bytes)
35 (defun sc-set-dirty (stream)
36 (with-stream-class (single-channel-simple-stream stream)
37 (setf (sm mode stream)
38 (if (<= (sm buffpos stream)
39 (sm buffer-ptr stream))
44 (defun sc-set-clean (stream)
45 (with-stream-class (single-channel-simple-stream stream)
46 (setf (sm mode stream) 0)))
48 (defun sc-dirty-p (stream)
49 (with-stream-class (single-channel-simple-stream stream)
50 (> (sm mode stream) 0)))
52 (defun flush-buffer (stream blocking)
53 (with-stream-class (single-channel-simple-stream stream)
55 (bytes (sm buffpos stream)))
56 (declare (type fixnum ptr bytes))
57 (when (and (> (sm mode stream) 0) (> (sm buffer-ptr stream) 0))
58 ;; The data read in from the file could have been changed if
59 ;; the stream is opened in read-write mode -- write back
60 ;; everything in the buffer at the correct position just in
62 (setf (device-file-position stream)
63 (- (device-file-position stream) (sm buffer-ptr stream))))
65 (when (>= ptr bytes) (setf (sm buffpos stream) 0) (setf (sm mode stream) 0) (return 0))
66 (let ((bytes-written (device-write stream nil ptr nil blocking)))
67 (declare (fixnum bytes-written))
68 (when (minusp bytes-written)
69 (error "DEVICE-WRITE error."))
70 (incf ptr bytes-written))))))
72 (defun flush-out-buffer (stream blocking)
73 (with-stream-class (dual-channel-simple-stream stream)
75 (bytes (sm outpos stream)))
76 (declare (type fixnum ptr bytes))
78 (when (>= ptr bytes) (setf (sm outpos stream) 0) (return 0))
79 (let ((bytes-written (device-write stream nil ptr nil blocking)))
80 (declare (fixnum bytes-written))
81 (when (minusp bytes-written)
82 (error "DEVICE-WRITE error."))
83 (incf ptr bytes-written))))))
85 (defun read-byte-internal (stream eof-error-p eof-value blocking)
86 (with-stream-class (simple-stream stream)
87 (let ((ptr (sm buffpos stream)))
88 (when (>= ptr (sm buffer-ptr stream))
89 (let ((bytes (device-read stream nil 0 nil blocking)))
90 (declare (type fixnum bytes))
92 (setf (sm buffer-ptr stream) bytes
94 (return-from read-byte-internal
95 (sb-impl::eof-or-lose stream eof-error-p eof-value)))))
96 (setf (sm buffpos stream) (1+ ptr))
97 (setf (sm last-char-read-size stream) 0)
98 (setf (sm charpos stream) nil)
99 (bref (sm buffer stream) ptr))))
101 ;;;; Single-Channel-Simple-Stream strategy functions
104 (declaim (ftype j-listen-fn sc-listen-ef))
105 (defun sc-listen-ef (stream)
106 (with-stream-class (simple-stream stream)
107 (let ((lcrs (sm last-char-read-size stream))
108 (buffer (sm buffer stream))
109 (buffpos (sm buffpos stream))
114 (when (>= buffpos (sm buffer-ptr stream))
115 (let ((bytes (refill-buffer stream nil)))
117 (return-from sc-listen-ef nil))
119 (return-from sc-listen-ef t))
121 (setf buffpos (sm buffpos stream))))))
122 (incf (sm last-char-read-size stream))
123 (prog1 (bref buffer buffpos)
127 (setq char (octets-to-char (sm external-format stream)
129 cnt #'input #'unput))
131 (setf (sm last-char-read-size stream) lcrs)))))
133 (declaim (ftype j-read-char-fn sc-read-char-ef))
134 (defun sc-read-char-ef (stream eof-error-p eof-value blocking)
135 #|(declare (optimize (speed 3) (space 2) (safety 0) (debug 0)))|#
136 (with-stream-class (simple-stream stream)
137 (let* ((buffer (sm buffer stream))
138 (buffpos (sm buffpos stream))
139 (ctrl (sm control-in stream))
140 (ef (sm external-format stream))
141 (state (sm oc-state stream)))
143 (when (>= buffpos (sm buffer-ptr stream))
144 (when (and (not (any-stream-instance-flags stream :dual :string))
146 (flush-buffer stream t))
147 (let ((bytes (refill-buffer stream blocking)))
149 (return-from sc-read-char-ef nil))
151 (return-from sc-read-char-ef
152 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
154 (setf buffpos (sm buffpos stream))))))
155 (incf (sm last-char-read-size stream))
156 (prog1 (bref buffer buffpos)
161 (char (octets-to-char ef state cnt #'input #'unput))
162 (code (char-code char)))
163 (setf (sm buffpos stream) buffpos
164 (sm last-char-read-size stream) cnt
165 (sm oc-state stream) state)
166 (when (and (< code 32) ctrl (svref ctrl code))
167 (setq char (funcall (the (or symbol function) (svref ctrl code))
170 (sb-impl::eof-or-lose stream eof-error-p eof-value)
174 (declaim (ftype j-read-char-fn sc-read-char-ef-mapped))
175 (defun sc-read-char-ef-mapped (stream eof-error-p eof-value blocking)
176 #|(declare (optimize (speed 3) (space 2) (safety 0) (debug 0)))|#
177 (declare (ignore blocking))
178 (with-stream-class (simple-stream stream)
179 (let* ((buffer (sm buffer stream))
180 (buffpos (sm buffpos stream))
181 (ctrl (sm control-in stream))
182 (ef (sm external-format stream))
183 (state (sm oc-state stream)))
185 (when (>= buffpos (sm buffer-ptr stream))
186 (return-from sc-read-char-ef-mapped
187 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
188 (incf (sm last-char-read-size stream))
189 (prog1 (bref buffer buffpos)
194 (char (octets-to-char ef state cnt #'input #'unput))
195 (code (char-code char)))
196 (setf (sm buffpos stream) buffpos
197 (sm last-char-read-size stream) cnt
198 (sm oc-state stream) state)
199 (when (and (< code 32) ctrl (svref ctrl code))
200 (setq char (funcall (the (or symbol function) (svref ctrl code))
203 (sb-impl::eof-or-lose stream eof-error-p eof-value)
207 (declaim (ftype j-read-chars-fn sc-read-chars-ef))
208 (defun sc-read-chars-ef (stream string search start end blocking)
209 ;; string is filled from START to END, or until SEARCH is found
210 ;; Return two values: count of chars read and
211 ;; NIL if SEARCH was not found
212 ;; T if SEARCH was found
213 ;; :EOF if eof encountered before end
214 (declare (type simple-stream stream)
216 (type (or null character) search)
217 (type fixnum start end)
218 (type boolean blocking)
219 #|(optimize (speed 3) (space 2) (safety 0) (debug 0))|#)
220 (with-stream-class (simple-stream stream)
221 (when (and (not (any-stream-instance-flags stream :dual :string))
223 (flush-buffer stream t))
224 (do ((buffer (sm buffer stream))
225 (buffpos (sm buffpos stream))
226 (buffer-ptr (sm buffer-ptr stream))
228 (ctrl (sm control-in stream))
229 (ef (sm external-format stream))
230 (state (sm oc-state stream))
231 (posn start (1+ posn))
232 (count 0 (1+ count)))
234 (setf (sm buffpos stream) buffpos
235 (sm last-char-read-size stream) lcrs
236 (sm oc-state stream) state)
238 (declare (type sb-int:index buffpos buffer-ptr posn count))
240 (when (>= buffpos buffer-ptr)
241 (setf (sm last-char-read-size stream) lcrs)
242 (let ((bytes (refill-buffer stream blocking)))
243 (declare (type fixnum bytes))
244 (setf buffpos (sm buffpos stream)
245 buffer-ptr (sm buffer-ptr stream))
246 (unless (plusp bytes)
247 (setf (sm buffpos stream) buffpos
248 (sm last-char-read-size stream) lcrs
249 (sm oc-state stream) state)
251 (return (values count nil))
252 (return (values count :eof))))))
253 (prog1 (bref buffer buffpos)
259 (char (octets-to-char ef state cnt #'input #'unput))
260 (code (char-code char)))
262 (when (and (< code 32) ctrl (svref ctrl code))
263 (setq char (funcall (the (or symbol function) (svref ctrl code))
266 (setf (sm buffpos stream) buffpos
267 (sm last-char-read-size stream) lcrs
268 (sm oc-state stream) state)
269 (return (values count :eof)))
270 ((and search (char= char search))
271 (setf (sm buffpos stream) buffpos
272 (sm last-char-read-size stream) lcrs
273 (sm oc-state stream) state)
274 (return (values count t)))
276 (setf (char string posn) char))))))))
279 (declaim (ftype j-read-chars-fn sc-read-chars-ef-mapped))
280 (defun sc-read-chars-ef-mapped (stream string search start end blocking)
281 ;; string is filled from START to END, or until SEARCH is found
282 ;; Return two values: count of chars read and
283 ;; NIL if SEARCH was not found
284 ;; T if SEARCH was found
285 ;; :EOF if eof encountered before end
286 (declare (type simple-stream stream)
288 (type (or null character) search)
289 (type fixnum start end)
290 (type boolean blocking)
292 #|(optimize (speed 3) (space 2) (safety 0) (debug 0))|#)
293 (with-stream-class (simple-stream stream)
294 ;; if stream is single-channel and mode == 3, flush buffer (if dirty)
295 (do ((buffer (sm buffer stream))
296 (buffpos (sm buffpos stream))
297 (buffer-ptr (sm buffer-ptr stream))
299 (ctrl (sm control-in stream))
300 (ef (sm external-format stream))
301 (state (sm oc-state stream))
302 (posn start (1+ posn))
303 (count 0 (1+ count)))
305 (setf (sm buffpos stream) buffpos
306 (sm last-char-read-size stream) lcrs
307 (sm oc-state stream) state)
309 (declare (type sb-int:index buffpos buffer-ptr posn count))
311 (when (>= buffpos buffer-ptr)
312 (return (values count :eof)))
313 (prog1 (bref buffer buffpos)
319 (char (octets-to-char ef state cnt #'input #'unput))
320 (code (char-code char)))
322 (when (and (< code 32) ctrl (svref ctrl code))
323 (setq char (funcall (the (or symbol function) (svref ctrl code))
326 (setf (sm buffpos stream) buffpos
327 (sm last-char-read-size stream) lcrs
328 (sm oc-state stream) state)
329 (return (values count :eof)))
330 ((and search (char= char search))
331 (setf (sm buffpos stream) buffpos
332 (sm last-char-read-size stream) lcrs
333 (sm oc-state stream) state)
334 (return (values count t)))
336 (setf (char string posn) char))))))))
339 (declaim (ftype j-unread-char-fn sc-unread-char-ef))
340 (defun sc-unread-char-ef (stream relaxed)
341 (declare (ignore relaxed))
342 (with-stream-class (simple-stream stream)
343 (let ((unread (sm last-char-read-size stream)))
344 (if (>= (sm buffpos stream) unread)
345 (decf (sm buffpos stream) unread)
346 (error "This shouldn't happen.")))))
348 (declaim (ftype j-write-char-fn sc-write-char-ef))
349 (defun sc-write-char-ef (character stream)
351 (with-stream-class (single-channel-simple-stream stream)
352 (let ((buffer (sm buffer stream))
353 (buffpos (sm buffpos stream))
354 (buf-len (sm buf-len stream))
355 (code (char-code character))
356 (ctrl (sm control-out stream)))
357 (when (and (< code 32) ctrl (svref ctrl code)
358 (funcall (the (or symbol function) (svref ctrl code))
360 (return-from sc-write-char-ef character))
361 (flet ((output (byte)
362 (when (>= buffpos buf-len)
363 (setf (sm buffpos stream) buffpos)
364 (setq buffpos (flush-buffer stream t)))
365 (setf (bref buffer buffpos) byte)
367 (char-to-octets (sm external-format stream) character
368 (sm co-state stream) #'output))
369 (setf (sm buffpos stream) buffpos)
370 (sc-set-dirty stream)
371 (if (sm charpos stream) (incf (sm charpos stream))))))
374 (declaim (ftype j-write-chars-fn sc-write-chars-ef))
375 (defun sc-write-chars-ef (string stream start end)
376 (with-stream-class (single-channel-simple-stream stream)
377 (do ((buffer (sm buffer stream))
378 (buffpos (sm buffpos stream))
379 (buf-len (sm buf-len stream))
380 (ef (sm external-format stream))
381 (ctrl (sm control-out stream))
382 (posn start (1+ posn))
383 (count 0 (1+ count)))
384 ((>= posn end) (setf (sm buffpos stream) buffpos) count)
385 (declare (type fixnum buffpos buf-len posn count))
386 (let* ((char (char string posn))
387 (code (char-code char)))
388 (unless (and (< code 32) ctrl (svref ctrl code)
389 (funcall (the (or symbol function) (svref ctrl code))
391 (flet ((output (byte)
392 (when (>= buffpos buf-len)
393 (setf (sm buffpos stream) buffpos)
394 (setq buffpos (flush-buffer stream t)))
395 (setf (bref buffer buffpos) byte)
397 (char-to-octets ef char (sm co-state stream) #'output))
398 (setf (sm buffpos stream) buffpos)
399 (if (sm charpos stream) (incf (sm charpos stream)))
400 (sc-set-dirty stream))))))
403 ;;;; Dual-Channel-Simple-Stream strategy functions
405 ;; single-channel read-side functions work for dual-channel streams too
407 (declaim (ftype j-write-char-fn dc-write-char-ef))
408 (defun dc-write-char-ef (character stream)
410 (with-stream-class (dual-channel-simple-stream stream)
411 (let ((out-buffer (sm out-buffer stream))
412 (outpos (sm outpos stream))
413 (max-out-pos (sm max-out-pos stream))
414 (code (char-code character))
415 (ctrl (sm control-out stream)))
416 (when (and (< code 32) ctrl (svref ctrl code)
417 (funcall (the (or symbol function) (svref ctrl code))
419 (return-from dc-write-char-ef character))
420 (flet ((output (byte)
421 (when (>= outpos max-out-pos)
422 (setf (sm outpos stream) outpos)
423 (setq outpos (flush-out-buffer stream t)))
424 (setf (bref out-buffer outpos) byte)
426 (char-to-octets (sm external-format stream) character
427 (sm co-state stream) #'output))
428 (setf (sm outpos stream) outpos)
429 (if (sm charpos stream) (incf (sm charpos stream))))))
433 (declaim (ftype j-write-chars-fn dc-write-chars-ef))
434 (defun dc-write-chars-ef (string stream start end)
435 (with-stream-class (dual-channel-simple-stream stream)
436 (do ((buffer (sm out-buffer stream))
437 (outpos (sm outpos stream))
438 (max-out-pos (sm max-out-pos stream))
439 (ef (sm external-format stream))
440 (ctrl (sm control-out stream))
441 (posn start (1+ posn))
442 (count 0 (1+ count)))
443 ((>= posn end) (setf (sm outpos stream) outpos) count)
444 (declare (type fixnum outpos max-out-pos posn count))
445 (let* ((char (char string posn))
446 (code (char-code char)))
447 (unless (and (< code 32) ctrl (svref ctrl code)
448 (funcall (the (or symbol function) (svref ctrl code))
450 (flet ((output (byte)
451 (when (>= outpos max-out-pos)
452 (setf (sm outpos stream) outpos)
453 (setq outpos (flush-out-buffer stream t)))
454 (setf (bref buffer outpos) byte)
456 (char-to-octets ef char (sm co-state stream) #'output))
457 (setf (sm outpos stream) outpos)
458 (if (sm charpos stream) (incf (sm charpos stream))))))))
460 ;;;; String-Simple-Stream strategy functions
462 (declaim (ftype j-read-char-fn str-read-char))
463 (defun str-read-char (stream eof-error-p eof-value blocking)
464 (declare (type string-input-simple-stream stream) (ignore blocking)
465 #|(optimize (speed 3) (space 2) (safety 0) (debug 0))|#
467 (with-stream-class (string-input-simple-stream stream)
468 (when (any-stream-instance-flags stream :eof)
469 (sb-impl::eof-or-lose stream eof-error-p eof-value))
470 (let* ((ptr (sm buffpos stream))
471 (char (if (< ptr (sm buffer-ptr stream))
472 (schar (sm buffer stream) ptr)
475 (sb-impl::eof-or-lose stream eof-error-p eof-value)
477 (setf (sm last-char-read-size stream) 1)
478 ;; do string-streams do control-in processing?
479 #|(let ((column (sm charpos stream)))
480 (declare (type (or null fixnum) column))
482 (setf (sm charpos stream) (1+ column))))
486 (declaim (ftype j-listen-fn str-listen-e-crlf))
487 (defun str-listen-e-crlf (stream)
488 (with-stream-class (composing-stream stream)
489 ;; if this says there's a character available, it may be #\Return,
490 ;; in which case read-char will only return if there's a following
491 ;; #\Linefeed, so this really has to read the char...
492 ;; but without precluding the later unread-char of a character which
493 ;; has already been read.
494 (funcall-stm-handler j-listen (sm melded-stream stream))))
496 (declaim (ftype j-read-char-fn str-read-char-e-crlf))
497 (defun str-read-char-e-crlf (stream eof-error-p eof-value blocking)
498 (with-stream-class (composing-stream stream)
499 (let* ((encap (sm melded-stream stream))
500 (ctrl (sm control-in stream))
501 (char (funcall-stm-handler j-read-char encap nil stream blocking)))
502 ;; if CHAR is STREAM, we hit EOF; if NIL, blocking is NIL and no
503 ;; character was available...
504 (when (eql char #\Return)
505 (let ((next (funcall-stm-handler j-read-char encap nil stream blocking)))
506 ;; if NEXT is STREAM, we hit EOF, so we should just return the
507 ;; #\Return (and mark the stream :EOF? At least unread if we
508 ;; got a soft EOF, from a terminal, etc.
509 ;; if NEXT is NIL, blocking is NIL and there's a CR but no
510 ;; LF available on the stream: have to unread the CR and
511 ;; return NIL, letting the CR be reread later.
513 ;; If we did get a linefeed, adjust the last-char-read-size
514 ;; so that an unread of the resulting newline will unread both
515 ;; the linefeed _and_ the carriage return.
516 (if (eql next #\Linefeed)
517 (setq char #\Newline)
518 (funcall-stm-handler j-unread-char encap nil))))
519 (when (characterp char)
520 (let ((code (char-code char)))
521 (when (and (< code 32) ctrl (svref ctrl code))
522 (setq char (funcall (the (or symbol function) (svref ctrl code))
525 (sb-impl::eof-or-lose stream eof-error-p eof-value)
528 (declaim (ftype j-unread-char-fn str-unread-char-e-crlf))
529 (defun str-unread-char-e-crlf (stream relaxed)
530 (declare (ignore relaxed))
531 (with-stream-class (composing-stream stream)
532 (funcall-stm-handler j-unread-char (sm melded-stream stream) nil)))
535 ;;; Functions to install the strategy functions in the appropriate slots
537 (defun melding-stream (stream)
538 (with-stream-class (simple-stream)
539 (do ((stm stream (sm melded-stream stm)))
540 ((eq (sm melded-stream stm) stream) stm))))
542 (defun meld (stream encap)
543 (with-stream-class (simple-stream)
544 (setf (sm melding-base encap) (sm melding-base stream))
545 (setf (sm melded-stream encap) (sm melded-stream stream))
546 (setf (sm melded-stream stream) encap)
547 (rotatef (sm j-listen encap) (sm j-listen stream))
548 (rotatef (sm j-read-char encap) (sm j-read-char stream))
549 (rotatef (sm j-read-chars encap) (sm j-read-chars stream))
550 (rotatef (sm j-unread-char encap) (sm j-unread-char stream))
551 (rotatef (sm j-write-char encap) (sm j-write-char stream))
552 (rotatef (sm j-write-chars encap) (sm j-write-chars stream))))
554 (defun unmeld (stream)
555 (with-stream-class (simple-stream)
556 (let ((encap (sm melded-stream stream)))
557 (unless (eq encap (sm melding-base stream))
558 (setf (sm melding-base encap) encap)
559 (setf (sm melded-stream stream) (sm melded-stream encap))
560 (setf (sm melded-stream encap) encap)
561 (rotatef (sm j-listen stream) (sm j-listen encap))
562 (rotatef (sm j-read-char encap) (sm j-read-char stream))
563 (rotatef (sm j-read-chars stream) (sm j-read-chars encap))
564 (rotatef (sm j-unread-char stream) (sm j-unread-char encap))
565 (rotatef (sm j-write-char stream) (sm j-write-char encap))
566 (rotatef (sm j-write-chars stream) (sm j-write-chars encap))))))
568 ;;; In cmucl, this is done with define-function-name-syntax (lists as
569 ;;; function names), we make do with symbol frobbing.
570 (defun %sf (kind name format &optional access)
571 (flet ((find-strategy-function (&rest args)
573 (find-symbol (format nil "~{~A~^-~}" (mapcar #'string args))
575 (if (fboundp name) (fdefinition name) nil))))
576 (or (find-strategy-function kind name format access)
577 (find-strategy-function kind name format)
578 (find-strategy-function kind name :ef access)
579 (find-strategy-function kind name :ef))))
582 (defun install-single-channel-character-strategy (stream external-format
584 (let ((format (find-external-format external-format)))
585 ;; ACCESS is usually NIL
586 ;; May be "undocumented" values: stream::buffer, stream::mapped
587 ;; to install strategies suitable for direct buffer streams
588 ;; (i.e., ones that call DEVICE-EXTEND instead of DEVICE-READ)
589 ;; (Avoids checking "mode" flags by installing special strategy)
590 (with-stream-class (simple-stream stream)
591 (setf (sm j-listen stream)
592 (%sf 'sc 'listen (ef-name format) access)
593 (sm j-read-char stream)
594 (%sf 'sc 'read-char (ef-name format) access)
595 (sm j-read-chars stream)
596 (%sf 'sc 'read-chars (ef-name format) access)
597 (sm j-unread-char stream)
598 (%sf 'sc 'unread-char (ef-name format) access)
599 (sm j-write-char stream)
600 (%sf 'sc 'write-char (ef-name format) access)
601 (sm j-write-chars stream)
602 (%sf 'sc 'write-chars (ef-name format) access))))
605 (defun install-dual-channel-character-strategy (stream external-format)
606 (let ((format (find-external-format external-format)))
607 (with-stream-class (simple-stream stream)
608 (setf (sm j-listen stream)
609 (%sf 'sc 'listen (ef-name format))
610 (sm j-read-char stream)
611 (%sf 'sc 'read-char (ef-name format))
612 (sm j-read-chars stream)
613 (%sf 'sc 'read-chars (ef-name format))
614 (sm j-unread-char stream)
615 (%sf 'sc 'unread-char (ef-name format))
616 (sm j-write-char stream)
617 (%sf 'dc 'write-char (ef-name format))
618 (sm j-write-chars stream)
619 (%sf 'dc 'write-chars (ef-name format)))))
622 ;; Deprecated -- use install-string-{input,output}-character-strategy instead!
623 (defun install-string-character-strategy (stream)
624 (when (any-stream-instance-flags stream :input)
625 (install-string-input-character-strategy stream))
626 (when (any-stream-instance-flags stream :output)
627 (install-string-output-character-strategy stream))
630 (defun install-string-input-character-strategy (stream)
632 (with-stream-class (simple-stream stream)
633 (setf (sm j-read-char stream) #'str-read-char))
636 (defun install-string-output-character-strategy (stream)
640 (defun install-composing-format-character-strategy (stream composing-format)
641 (let ((format composing-format))
642 (with-stream-class (simple-stream stream)
644 (:e-crlf (setf (sm j-read-char stream) #'str-read-char-e-crlf
645 (sm j-unread-char stream) #'str-unread-char-e-crlf))))
649 (defun compose-encapsulating-streams (stream external-format)
650 (when (consp external-format)
651 (with-stream-class (simple-stream)
652 (let ((encap (if (eq (sm melded-stream stream) stream)
654 (sm melded-stream stream))))
656 (setq encap (make-instance 'composing-stream))
658 (setf (stream-external-format encap) (car (last external-format)))
659 (setf (sm external-format stream) external-format)
660 (install-composing-format-character-strategy stream
661 (butlast external-format))
664 (defmethod (setf stream-external-format) (ef (stream simple-stream))
665 (with-stream-class (simple-stream stream)
666 (setf (sm external-format stream) (find-external-format ef)))
670 ;;; NULL STRATEGY FUNCTIONS
673 (declaim (ftype j-read-char-fn null-read-char))
674 (defun null-read-char (stream eof-error-p eof-value blocking)
675 (declare (ignore blocking))
676 (sb-impl::eof-or-lose stream eof-error-p eof-value))
678 (declaim (ftype j-read-chars-fn null-read-chars))
679 (defun null-read-chars (stream string search start end blocking)
680 (declare (ignore stream string search start end blocking))
683 (declaim (ftype j-unread-char-fn null-unread-char))
684 (defun null-unread-char (stream relaxed)
685 (declare (ignore stream relaxed)))
687 (declaim (ftype j-write-char-fn null-write-char))
688 (defun null-write-char (character stream)
689 (declare (ignore stream))
692 (declaim (ftype j-write-chars-fn null-write-chars))
693 (defun null-write-chars (string stream start end)
694 (declare (ignore string stream))
697 (declaim (ftype j-listen-fn null-listen))
698 (defun null-listen (stream)
699 (declare (ignore stream))