0.8.7.3
[sbcl.git] / src / code / fd-stream.lisp
index 91b8f86..2fbafbf 100644 (file)
                                  (+ (fd-stream-obuf-tail stream)
                                     ,size))
                           (flush-output-buffer stream)))
+                    ,(unless (eq (car buffering) :none)
+                       `(when (> (fd-stream-ibuf-tail stream)
+                                 (fd-stream-ibuf-head stream))
+                          (file-position stream (file-position stream))))
+                    
                     ,@body
                     (incf (fd-stream-obuf-tail stream) ,size)
                     ,(ecase (car buffering)
   (let ((start (or start 0))
        (end (or end (length (the (simple-array * (*)) thing)))))
     (declare (type index start end))
+    (when (> (fd-stream-ibuf-tail fd-stream)
+            (fd-stream-ibuf-head fd-stream))
+      (file-position fd-stream (file-position fd-stream)))
     (let* ((len (fd-stream-obuf-length fd-stream))
           (tail (fd-stream-obuf-tail fd-stream))
           (space (- len tail))
 ;;; Note that this blocks in UNIX-READ. It is generally used where
 ;;; there is a definite amount of reading to be done, so blocking
 ;;; isn't too problematical.
-(defun fd-stream-read-n-bytes (stream buffer start requested eof-error-p)
+(defun fd-stream-read-n-bytes (stream buffer start requested eof-error-p
+                              &aux (total-copied 0))
   (declare (type file-stream stream))
-  (declare (type index start requested))
-  (do ((total-copied 0))
+  (declare (type index start requested total-copied))
+  (let ((unread (fd-stream-unread stream)))
+    (when unread
+      ;; AVERs designed to fail when we have more complicated
+      ;; character representations.
+      (aver (typep unread 'base-char))
+      (aver (= (fd-stream-element-size stream) 1))
+      ;; KLUDGE: this is a slightly-unrolled-and-inlined version of
+      ;; %BYTE-BLT
+      (etypecase buffer
+       (system-area-pointer
+        (setf (sap-ref-8 buffer start) (char-code unread)))
+       ((simple-unboxed-array (*))
+        (setf (aref buffer start) unread)))
+      (setf (fd-stream-unread stream) nil)
+      (setf (fd-stream-listen stream) nil)
+      (incf total-copied)))
+  (do ()
       (nil)
-    (declare (type index total-copied))
     (let* ((remaining-request (- requested total-copied))
           (head (fd-stream-ibuf-head stream))
           (tail (fd-stream-ibuf-tail stream))
                  (fd-stream-bin fd-stream) routine))
        (when (eql size 1)
          (setf (fd-stream-n-bin fd-stream) #'fd-stream-read-n-bytes)
-         (when buffer-p
+         (when (and buffer-p
+                    ;; We only create this buffer for streams of type
+                    ;; (unsigned-byte 8).  Because there's no buffer, the
+                    ;; other element-types will dispatch to the appropriate
+                    ;; input (output) routine in fast-read-byte.
+                    (equal target-type '(unsigned-byte 8))
+                    #+nil
+                    (or (eq type 'unsigned-byte)
+                        (eq type :default)))
            (setf (ansi-stream-in-buffer fd-stream)
                  (make-array +ansi-stream-in-buffer-length+
                              :element-type '(unsigned-byte 8)))))
     (:element-type
      (fd-stream-element-type fd-stream))
     (:interactive-p
-      ;; FIXME: sb!unix:unix-isatty is undefined.
      (= 1 (the (member 0 1)
             (sb!unix:unix-isatty (fd-stream-fd fd-stream)))))
     (:line-length
 
 (defun fd-stream-file-position (stream &optional newpos)
   (declare (type file-stream stream)
-          (type (or index (member nil :start :end)) newpos))
+          (type (or (alien sb!unix:off-t) (member nil :start :end)) newpos))
   (if (null newpos)
       (sb!sys:without-interrupts
        ;; First, find the position of the UNIX file descriptor in the file.
        (multiple-value-bind (posn errno)
            (sb!unix:unix-lseek (fd-stream-fd stream) 0 sb!unix:l_incr)
-         (declare (type (or index null) posn))
-         (cond ((fixnump posn)
+         (declare (type (or (alien sb!unix:off-t) null) posn))
+         (cond ((integerp posn)
                 ;; Adjust for buffered output: If there is any output
                 ;; buffered, the *real* file position will be larger
                 ;; than reported by lseek() because lseek() obviously
                 ;; cannot take into account output we have not sent
                 ;; yet.
                 (dolist (later (fd-stream-output-later stream))
-                  (incf posn (- (the index (caddr later))
-                                (the index (cadr later)))))
+                  (incf posn (- (caddr later)
+                                (cadr later))))
                 (incf posn (fd-stream-obuf-tail stream))
                 ;; Adjust for unread input: If there is any input
                 ;; read from UNIX but not supplied to the user of the
                                         stream
                                         errno))))))
       (let ((offset 0) origin)
-       (declare (type index offset))
+       (declare (type (alien sb!unix:off-t) offset))
        ;; Make sure we don't have any output pending, because if we
        ;; move the file pointer before writing this stuff, it will be
        ;; written in the wrong location.
               (setf offset 0 origin sb!unix:l_set))
              ((eq newpos :end)
               (setf offset 0 origin sb!unix:l_xtnd))
-             ((typep newpos 'index)
+             ((typep newpos '(alien sb!unix:off-t))
               (setf offset (* newpos (fd-stream-element-size stream))
                     origin sb!unix:l_set))
              (t
               (error "invalid position given to FILE-POSITION: ~S" newpos)))
        (multiple-value-bind (posn errno)
            (sb!unix:unix-lseek (fd-stream-fd stream) offset origin)
-         (cond ((typep posn 'fixnum)
+         (cond ((typep posn '(alien sb!unix:off-t))
                 t)
                ((eq errno sb!unix:espipe)
                 nil)
                      (open-error "~@<The path ~2I~_~S ~I~_does not exist.~:>"
                                  pathname))
                     (t nil)))
-                 ((and (eql errno sb!unix:eexist) if-exists)
+                 ((and (eql errno sb!unix:eexist) (null if-exists))
                   nil)
                  (t
                   (vanilla-open-error)))))))))