3 ;;; **********************************************************************
4 ;;; This code was written by Paul Foley and has been placed in the public
8 ;;; Sbcl port by Rudi Schlatte.
11 ;;; **********************************************************************
13 ;;; Macros needed by the simple-streams implementation
15 (in-package "SB-SIMPLE-STREAMS")
17 (defmacro def-stream-class (name superclasses slots &rest options)
18 `(defclass ,name ,superclasses ,slots ,@options))
21 ;; All known stream flags. Note that the position in the constant
22 ;; list is significant (cf. %flags below).
23 (sb-int:defconstant-eqx +flag-bits+
24 '(:simple ; instance is valid
25 :input :output ; direction
26 :dual :string ; type of stream
28 :dirty ; output buffer needs write
29 :interactive) ; interactive stream
32 (eval-when (:compile-toplevel :load-toplevel :execute)
34 (loop for flag in flags
35 as pos = (position flag +flag-bits+)
36 when (eq flag :gray) do
37 (error "Gray streams not supported.")
39 sum (ash 1 pos) into bits
41 collect flag into unused
43 (warn "Invalid stream instance flag~P: ~{~S~^, ~}"
44 (length unused) unused))
47 ;;; Setup an environment where sm, funcall-stm-handler and
48 ;;; funcall-stm-handler-2 are valid and efficient for a stream of type
49 ;;; class-name or for the stream argument (in which case the
50 ;;; class-name argument is ignored). In nested with-stream-class
51 ;;; forms, the inner with-stream-class form must specify a stream
52 ;;; argument if the outer one specifies one, or the wrong object will
55 (defmacro with-stream-class ((class-name &optional stream) &body body)
57 (let ((stm (gensym "STREAM"))
59 `(let* ((,stm ,stream)
60 (,slt (sb-kernel:%instance-ref ,stm 1)))
61 (declare (type ,class-name ,stm)
62 (type simple-vector ,slt)
64 (macrolet ((sm (slot-name stream)
65 (declare (ignore stream))
67 `(slot-value ,',stm ',slot-name)
69 `(%sm ',slot-name ,',stm))
70 (add-stream-instance-flags (stream &rest flags)
71 (declare (ignore stream))
72 `(setf (sm %flags ,',stm) (logior (the fixnum (sm %flags ,',stm))
74 (remove-stream-instance-flags (stream &rest flags)
75 (declare (ignore stream))
76 `(setf (sm %flags ,',stm) (logandc2 (the fixnum (sm %flags ,',stm))
78 (any-stream-instance-flags (stream &rest flags)
79 (declare (ignore stream))
80 `(not (zerop (logand (the fixnum (sm %flags ,',stm))
83 `(macrolet ((sm (slot-name stream)
85 `(slot-value ,stream ',slot-name)
87 `(%sm ',slot-name ,stream)))
90 (defmacro sm (slot-name stream)
91 "Access the named slot in Stream."
92 (warn "Using ~S macro outside ~S." 'sm 'with-stream-class)
93 `(slot-value ,stream ',slot-name))
95 (defmacro funcall-stm-handler (slot-name stream &rest args)
96 "Call the strategy function named by Slot-Name on Stream."
99 (funcall (sm ,slot-name ,s) ,s ,@args))))
101 (defmacro funcall-stm-handler-2 (slot-name arg1 stream &rest args)
102 "Call the strategy function named by Slot-Name on Stream."
105 (funcall (sm ,slot-name ,s) ,arg1 ,s ,@args))))
107 (defmacro add-stream-instance-flags (stream &rest flags)
108 "Set the given Flags in Stream."
109 (let ((s (gensym "STREAM")))
111 (with-stream-class (simple-stream ,s)
112 (add-stream-instance-flags ,s ,@flags)))))
114 (defmacro remove-stream-instance-flags (stream &rest flags)
115 "Clear the given Flags in Stream."
116 (let ((s (gensym "STREAM")))
118 (with-stream-class (simple-stream ,s)
119 (remove-stream-instance-flags ,s ,@flags)))))
121 (defmacro any-stream-instance-flags (stream &rest flags)
122 "Determine whether any one of the Flags is set in Stream."
123 (let ((s (gensym "STREAM")))
125 (with-stream-class (simple-stream ,s)
126 (any-stream-instance-flags ,s ,@flags)))))
128 (defmacro simple-stream-dispatch (stream single dual string)
129 (let ((s (gensym "STREAM")))
131 (with-stream-class (simple-stream ,s)
132 (let ((%flags (sm %flags ,s)))
133 (cond ((zerop (logand %flags ,(%flags '(:string :dual))))
135 ((zerop (logand %flags ,(%flags '(:string))))
140 (defmacro simple-stream-dispatch-2 (stream non-string string)
141 (let ((s (gensym "STREAM")))
143 (with-stream-class (simple-stream ,s)
144 (let ((%flags (sm %flags ,s)))
145 (cond ((zerop (logand %flags ,(%flags '(:string))))
151 ;;;; The following two forms are for Franz source-compatibility,
152 ;;;; disabled at the moment.
156 (:use "SB-SIMPLE-STREAMS")
157 (:import-from "SB-SIMPLE-STREAMS"
158 "BUFFER" "BUFFPOS" "BUFFER-PTR"
159 "OUT-BUFFER" "MAX-OUT-POS"
160 "INPUT-HANDLE" "OUTPUT-HANDLE"