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 (defun %file-namestring
(pathname)
18 (sb-ext:native-namestring
(sb-int:physicalize-pathname pathname
) :as-file t
))
20 (defmacro def-stream-class
(name superclasses slots
&rest options
)
21 `(defclass ,name
,superclasses
,slots
,@options
))
24 ;; All known stream flags. Note that the position in the constant
25 ;; list is significant (cf. %flags below).
26 (sb-int:defconstant-eqx
+flag-bits
+
27 '(:simple
; instance is valid
28 :input
:output
; direction
29 :dual
:string
; type of stream
31 :dirty
; output buffer needs write
32 :interactive
) ; interactive stream
35 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
37 (loop for flag in flags
38 as pos
= (position flag
+flag-bits
+)
39 when
(eq flag
:gray
) do
40 (error "Gray streams not supported.")
42 sum
(ash 1 pos
) into bits
44 collect flag into unused
46 (warn "Invalid stream instance flag~P: ~{~S~^, ~}"
47 (length unused
) unused
))
50 ;;; Setup an environment where sm, funcall-stm-handler and
51 ;;; funcall-stm-handler-2 are valid and efficient for a stream of type
52 ;;; class-name or for the stream argument (in which case the
53 ;;; class-name argument is ignored). In nested with-stream-class
54 ;;; forms, the inner with-stream-class form must specify a stream
55 ;;; argument if the outer one specifies one, or the wrong object will
58 (defmacro with-stream-class
((class-name &optional stream
) &body body
)
60 (let ((stm (gensym "STREAM"))
62 `(let* ((,stm
,stream
)
63 (,slt
(sb-kernel:%instance-ref
,stm
1)))
64 (declare (type ,class-name
,stm
)
65 (type simple-vector
,slt
)
67 (macrolet ((sm (slot-name stream
)
68 (declare (ignore stream
))
70 `(slot-value ,',stm
',slot-name
)
72 `(%sm
',slot-name
,',stm
))
73 (add-stream-instance-flags (stream &rest flags
)
74 (declare (ignore stream
))
75 `(setf (sm %flags
,',stm
) (logior (the fixnum
(sm %flags
,',stm
))
77 (remove-stream-instance-flags (stream &rest flags
)
78 (declare (ignore stream
))
79 `(setf (sm %flags
,',stm
) (logandc2 (the fixnum
(sm %flags
,',stm
))
81 (any-stream-instance-flags (stream &rest flags
)
82 (declare (ignore stream
))
83 `(not (zerop (logand (the fixnum
(sm %flags
,',stm
))
86 `(macrolet ((sm (slot-name stream
)
88 `(slot-value ,stream
',slot-name
)
90 `(%sm
',slot-name
,stream
)))
93 (defmacro sm
(slot-name stream
)
94 "Access the named slot in Stream."
95 (warn "Using ~S macro outside ~S." 'sm
'with-stream-class
)
96 `(slot-value ,stream
',slot-name
))
98 (defmacro funcall-stm-handler
(slot-name stream
&rest args
)
99 "Call the strategy function named by Slot-Name on Stream."
102 (funcall (sm ,slot-name
,s
) ,s
,@args
))))
104 (defmacro funcall-stm-handler-2
(slot-name arg1 stream
&rest args
)
105 "Call the strategy function named by Slot-Name on Stream."
108 (funcall (sm ,slot-name
,s
) ,arg1
,s
,@args
))))
110 (defmacro add-stream-instance-flags
(stream &rest flags
)
111 "Set the given Flags in Stream."
112 (let ((s (gensym "STREAM")))
114 (with-stream-class (simple-stream ,s
)
115 (add-stream-instance-flags ,s
,@flags
)))))
117 (defmacro remove-stream-instance-flags
(stream &rest flags
)
118 "Clear the given Flags in Stream."
119 (let ((s (gensym "STREAM")))
121 (with-stream-class (simple-stream ,s
)
122 (remove-stream-instance-flags ,s
,@flags
)))))
124 (defmacro any-stream-instance-flags
(stream &rest flags
)
125 "Determine whether any one of the Flags is set in Stream."
126 (let ((s (gensym "STREAM")))
128 (with-stream-class (simple-stream ,s
)
129 (any-stream-instance-flags ,s
,@flags
)))))
131 (defmacro simple-stream-dispatch
(stream single dual string
)
132 (let ((s (gensym "STREAM")))
134 (with-stream-class (simple-stream ,s
)
135 (let ((%flags
(sm %flags
,s
)))
136 (cond ((zerop (logand %flags
,(%flags
'(:string
:dual
))))
138 ((zerop (logand %flags
,(%flags
'(:string
))))
143 (defmacro simple-stream-dispatch-2
(stream non-string string
)
144 (let ((s (gensym "STREAM")))
146 (with-stream-class (simple-stream ,s
)
147 (let ((%flags
(sm %flags
,s
)))
148 (cond ((zerop (logand %flags
,(%flags
'(:string
))))
154 ;;;; The following two forms are for Franz source-compatibility,
155 ;;;; disabled at the moment.
159 (:use
"SB-SIMPLE-STREAMS")
160 (:import-from
"SB-SIMPLE-STREAMS"
161 "BUFFER" "BUFFPOS" "BUFFER-PTR"
162 "OUT-BUFFER" "MAX-OUT-POS"
163 "INPUT-HANDLE" "OUTPUT-HANDLE"