X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Ffd-stream.lisp;h=07dfaf1af1f66a3da8a7132d7cc1d179acbf536c;hb=f71445c16693bf12ac835a46763e1dfb25a6db0a;hp=82da2b393e31661c136febd00045a05e9e2728ac;hpb=8151587cdfac76dfdebe98caf4790839ff5aaa38;p=sbcl.git diff --git a/src/code/fd-stream.lisp b/src/code/fd-stream.lisp index 82da2b3..07dfaf1 100644 --- a/src/code/fd-stream.lisp +++ b/src/code/fd-stream.lisp @@ -157,6 +157,8 @@ (element-type 'base-char) ;; the Unix file descriptor (fd -1 :type fixnum) + ;; What do we know about the FD? + (fd-type :unknown :type keyword) ;; controls when the output buffer is flushed (buffering :full :type (member :full :line :none)) ;; controls whether the input buffer must be cleared before output @@ -187,7 +189,8 @@ (timeout nil :type (or single-float null)) ;; pathname of the file this stream is opened to (returned by PATHNAME) (pathname nil :type (or pathname null)) - (external-format :default) + ;; Not :DEFAULT, because we want to match CHAR-SIZE! + (external-format :latin-1) ;; fixed width, or function to call with a character (char-size 1 :type (or fixnum function)) (output-bytes #'ill-out :type function) @@ -406,14 +409,10 @@ ;;; this is not something we want to export. Nikodemus thinks the ;;; right thing is to support a low-level non-stream like IO layer, ;;; akin to java.nio. -(defun output-raw-bytes (stream thing &optional start end) +(declaim (inline output-raw-bytes)) +(define-deprecated-function :late "1.0.8.16" output-raw-bytes write-sequence + (stream thing &optional start end) (write-or-buffer-output stream thing (or start 0) (or end (length thing)))) - -(define-compiler-macro output-raw-bytes (stream thing &optional start end) - (deprecation-warning 'output-raw-bytes) - (let ((x (gensym "THING"))) - `(let ((,x ,thing)) - (write-or-buffer-output ,stream ,x (or ,start 0) (or ,end (length ,x)))))) ;;;; output routines and related noise @@ -791,6 +790,11 @@ (octets-to-string-fun (missing-arg) :type function) (string-to-octets-fun (missing-arg) :type function)) +(defun ef-char-size (ef-entry) + (if (variable-width-external-format-p ef-entry) + (bytes-for-char-fun ef-entry) + (funcall (bytes-for-char-fun ef-entry) #\x))) + (defun wrap-external-format-functions (external-format fun) (let ((result (%copy-external-format external-format))) (macrolet ((frob (accessor) @@ -851,7 +855,7 @@ (defun get-external-format-or-lose (external-format) (or (get-external-format external-format) - (error "Undefined external-format ~A" external-format))) + (error "Undefined external-format: ~S" external-format))) (defun external-format-keyword (external-format) (typecase external-format @@ -871,17 +875,17 @@ ;;; number of bytes per element. (defun pick-output-routine (type buffering &optional external-format) (when (subtypep type 'character) - (let ((entry (get-external-format external-format))) - (when entry - (return-from pick-output-routine - (values (ecase buffering - (:none (ef-write-char-none-buffered-fun entry)) - (:line (ef-write-char-line-buffered-fun entry)) - (:full (ef-write-char-full-buffered-fun entry))) - 'character - 1 - (ef-write-n-bytes-fun entry) - (canonize-external-format external-format entry)))))) + (let ((entry (get-external-format-or-lose external-format))) + (return-from pick-output-routine + (values (ecase buffering + (:none (ef-write-char-none-buffered-fun entry)) + (:line (ef-write-char-line-buffered-fun entry)) + (:full (ef-write-char-full-buffered-fun entry))) + 'character + 1 + (ef-write-n-bytes-fun entry) + (ef-char-size entry) + (canonize-external-format external-format entry))))) (dolist (entry *output-routines*) (when (and (subtypep type (first entry)) (eq buffering (second entry)) @@ -968,11 +972,9 @@ (count 0)) (tagbody ;; Check for blocking input before touching the stream if we are to - ;; serve events: if the FD is blocking, we don't want to hang on the - ;; write if we are to serve events or notice timeouts. - (if (and (or (fd-stream-serve-events stream) - (fd-stream-timeout stream) - *deadline*) + ;; serve events: if the FD is blocking, we don't want to try an uninterruptible + ;; read(). Regular files should never block, so we can elide the check. + (if (and (neq :regular (fd-stream-fd-type stream)) (sysread-may-block-p stream)) (go :wait-for-input) (go :main)) @@ -1221,14 +1223,14 @@ ;;; bytes per element (and for character types string input routine). (defun pick-input-routine (type &optional external-format) (when (subtypep type 'character) - (let ((entry (get-external-format external-format))) - (when entry - (return-from pick-input-routine - (values (ef-read-char-fun entry) - 'character - 1 - (ef-read-n-chars-fun entry) - (canonize-external-format external-format entry)))))) + (let ((entry (get-external-format-or-lose external-format))) + (return-from pick-input-routine + (values (ef-read-char-fun entry) + 'character + 1 + (ef-read-n-chars-fun entry) + (ef-char-size entry) + (canonize-external-format external-format entry))))) (dolist (entry *input-routines*) (when (and (subtypep type (first entry)) (or (not (fourth entry)) @@ -1702,6 +1704,7 @@ (character-stream-p (subtypep target-type 'character)) (bivalent-stream-p (eq element-type :default)) normalized-external-format + char-size (bin-routine #'ill-bin) (bin-type nil) (bin-size nil) @@ -1745,24 +1748,23 @@ (when output-p (setf (fd-stream-char-pos fd-stream) 0)) - (when (and character-stream-p - (eq external-format :default)) + (when (and character-stream-p (eq external-format :default)) (/show0 "/getting default external format") (setf external-format (default-external-format))) (when input-p (when (or (not character-stream-p) bivalent-stream-p) - (multiple-value-setq (bin-routine bin-type bin-size read-n-characters - normalized-external-format) - (pick-input-routine (if bivalent-stream-p '(unsigned-byte 8) - target-type) - external-format)) + (setf (values bin-routine bin-type bin-size read-n-characters + char-size normalized-external-format) + (pick-input-routine (if bivalent-stream-p '(unsigned-byte 8) + target-type) + external-format)) (unless bin-routine (error "could not find any input routine for ~S" target-type))) (when character-stream-p - (multiple-value-setq (cin-routine cin-type cin-size read-n-characters - normalized-external-format) - (pick-input-routine target-type external-format)) + (setf (values cin-routine cin-type cin-size read-n-characters + char-size normalized-external-format) + (pick-input-routine target-type external-format)) (unless cin-routine (error "could not find any input routine for ~S" target-type))) (setf (fd-stream-in fd-stream) cin-routine @@ -1771,8 +1773,8 @@ (setf input-size (or cin-size bin-size)) (setf input-type (or cin-type bin-type)) (when normalized-external-format - (setf (fd-stream-external-format fd-stream) - normalized-external-format)) + (setf (fd-stream-external-format fd-stream) normalized-external-format + (fd-stream-char-size fd-stream) char-size)) (when (= (or cin-size 1) (or bin-size 1) 1) (setf (fd-stream-n-bin fd-stream) ;XXX (if (and character-stream-p (not bivalent-stream-p)) @@ -1799,33 +1801,33 @@ (when output-p (when (or (not character-stream-p) bivalent-stream-p) - (multiple-value-setq (bout-routine bout-type bout-size output-bytes - normalized-external-format) - (let ((buffering (fd-stream-buffering fd-stream))) - (if bivalent-stream-p - (pick-output-routine '(unsigned-byte 8) - (if (eq :line buffering) - :full - buffering) - external-format) - (pick-output-routine target-type buffering external-format)))) + (setf (values bout-routine bout-type bout-size output-bytes + char-size normalized-external-format) + (let ((buffering (fd-stream-buffering fd-stream))) + (if bivalent-stream-p + (pick-output-routine '(unsigned-byte 8) + (if (eq :line buffering) + :full + buffering) + external-format) + (pick-output-routine target-type buffering external-format)))) (unless bout-routine (error "could not find any output routine for ~S buffered ~S" (fd-stream-buffering fd-stream) target-type))) (when character-stream-p - (multiple-value-setq (cout-routine cout-type cout-size output-bytes - normalized-external-format) - (pick-output-routine target-type - (fd-stream-buffering fd-stream) - external-format)) + (setf (values cout-routine cout-type cout-size output-bytes + char-size normalized-external-format) + (pick-output-routine target-type + (fd-stream-buffering fd-stream) + external-format)) (unless cout-routine (error "could not find any output routine for ~S buffered ~S" (fd-stream-buffering fd-stream) target-type))) (when normalized-external-format - (setf (fd-stream-external-format fd-stream) - normalized-external-format)) + (setf (fd-stream-external-format fd-stream) normalized-external-format + (fd-stream-char-size fd-stream) char-size)) (when character-stream-p (setf (fd-stream-output-bytes fd-stream) output-bytes)) (setf (fd-stream-out fd-stream) cout-routine @@ -2215,6 +2217,7 @@ ((not (or input output)) (error "File descriptor must be opened either for input or output."))) (let ((stream (%make-fd-stream :fd fd + :fd-type (sb!unix:fd-type fd) :name name :file file :original original @@ -2222,9 +2225,7 @@ :pathname pathname :buffering buffering :dual-channel-p dual-channel-p - :external-format external-format :bivalent-p (eq element-type :default) - :char-size (external-format-char-size external-format) :serve-events serve-events :timeout (if timeout