1 ;;;; streams for UNIX file descriptors
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!IMPL")
16 ;;;; Streams hold BUFFER objects, which contain a SAP, size of the
17 ;;;; memory area the SAP stands for (LENGTH bytes), and HEAD and TAIL
18 ;;;; indexes which delimit the "valid", or "active" area of the
19 ;;;; memory. HEAD is inclusive, TAIL is exclusive.
21 ;;;; Buffers get allocated lazily, and are recycled by returning them
22 ;;;; to the *AVAILABLE-BUFFERS* list. Every buffer has it's own
23 ;;;; finalizer, to take care of releasing the SAP memory when a stream
24 ;;;; is not properly closed.
26 ;;;; The code aims to provide a limited form of thread and interrupt
27 ;;;; safety: parallel writes and reads may lose output or input, cause
28 ;;;; interleaved IO, etc -- but they should not corrupt memory. The
29 ;;;; key to doing this is to read buffer state once, and update the
30 ;;;; state based on the read state:
32 ;;;; (let ((tail (buffer-tail buffer)))
34 ;;;; (setf (buffer-tail buffer) (+ tail n)))
38 ;;;; (let ((tail (buffer-tail buffer)))
40 ;;;; (incf (buffer-tail buffer) n))
43 (declaim (inline buffer-sap buffer-length buffer-head buffer-tail
44 (setf buffer-head
) (setf buffer-tail
)))
45 (defstruct (buffer (:constructor %make-buffer
(sap length
)))
46 (sap (missing-arg) :type system-area-pointer
:read-only t
)
47 (length (missing-arg) :type index
:read-only t
)
51 (defvar *available-buffers
* ()
53 "List of available buffers.")
55 (defvar *available-buffers-spinlock
* (sb!thread
::make-spinlock
56 :name
"lock for *AVAILABLE-BUFFERS*")
58 "Mutex for access to *AVAILABLE-BUFFERS*.")
60 (defmacro with-available-buffers-lock
((&optional
) &body body
)
61 ;; CALL-WITH-SYSTEM-SPINLOCK because
63 ;; 1. streams are low-level enough to be async signal safe, and in
64 ;; particular a C-c that brings up the debugger while holding the
65 ;; mutex would lose badly
67 ;; 2. this can potentially be a fairly busy (but also probably
68 ;; uncontended) lock, so we don't want to pay the syscall per
69 ;; release -- hence a spinlock.
71 ;; ...again, once we have smarted locks the spinlock here can become
73 `(sb!thread
::call-with-system-spinlock
(lambda () ,@body
)
74 *available-buffers-spinlock
*))
76 (defconstant +bytes-per-buffer
+ (* 4 1024)
78 "Default number of bytes per buffer.")
80 (defun alloc-buffer (&optional
(size +bytes-per-buffer
+))
81 ;; Don't want to allocate & unwind before the finalizer is in place.
83 (let* ((sap (allocate-system-memory size
))
84 (buffer (%make-buffer sap size
)))
85 (when (zerop (sap-int sap
))
86 (error "Could not allocate ~D bytes for buffer." size
))
87 (finalize buffer
(lambda ()
88 (deallocate-system-memory sap size
))
93 ;; Don't go for the lock if there is nothing to be had -- sure,
94 ;; another thread might just release one before we get it, but that
95 ;; is not worth the cost of locking. Also release the lock before
96 ;; allocation, since it's going to take a while.
97 (if *available-buffers
*
98 (or (with-available-buffers-lock ()
99 (pop *available-buffers
*))
103 (declaim (inline reset-buffer
))
104 (defun reset-buffer (buffer)
105 (setf (buffer-head buffer
) 0
106 (buffer-tail buffer
) 0)
109 (defun release-buffer (buffer)
110 (reset-buffer buffer
)
111 (with-available-buffers-lock ()
112 (push buffer
*available-buffers
*)))
114 ;;; This is a separate buffer management function, as it wants to be
115 ;;; clever about locking -- grabbing the lock just once.
116 (defun release-fd-stream-buffers (fd-stream)
117 (let ((ibuf (fd-stream-ibuf fd-stream
))
118 (obuf (fd-stream-obuf fd-stream
))
119 (queue (loop for item in
(fd-stream-output-queue fd-stream
)
121 collect
(reset-buffer item
))))
123 (push (reset-buffer ibuf
) queue
))
125 (push (reset-buffer obuf
) queue
))
126 ;; ...so, anything found?
128 ;; detach from stream
129 (setf (fd-stream-ibuf fd-stream
) nil
130 (fd-stream-obuf fd-stream
) nil
131 (fd-stream-output-queue fd-stream
) nil
)
132 ;; splice to *available-buffers*
133 (with-available-buffers-lock ()
134 (setf *available-buffers
* (nconc queue
*available-buffers
*))))))
136 ;;;; the FD-STREAM structure
138 (defstruct (fd-stream
139 (:constructor %make-fd-stream
)
140 (:conc-name fd-stream-
)
141 (:predicate fd-stream-p
)
142 (:include ansi-stream
143 (misc #'fd-stream-misc-routine
))
146 ;; the name of this stream (should be deprecated: this slot's
147 ;; purpose is better served with PRINT-OBJECT methods).
149 ;; the file this stream is for (Deprecated: we now store the
150 ;; truename, rather than a string, in the TRUENAME slot. Nothing in
151 ;; SBCL should use this slot anymore; if you're looking at this
152 ;; because we broke your use of FD-STREAMs, you're probably doing
154 (file nil
:type null
:read-only t
)
156 ;; Deprecated. We don't use these anymore, and you shouldn't either.
157 (original nil
:type null
:read-only t
)
158 (delete-original nil
:type null
:read-only t
)
159 ;;; the number of bytes per element
160 (element-size 1 :type index
)
161 ;; the type of element being transfered
162 (element-type 'base-char
)
163 ;; the Unix file descriptor
165 ;; controls when the output buffer is flushed
166 (buffering :full
:type
(member :full
:line
:none
))
167 ;; controls whether the input buffer must be cleared before output
168 ;; (must be done for files, not for sockets, pipes and other data
169 ;; sources where input and output aren't related). non-NIL means
170 ;; don't clear input buffer.
172 ;; character position if known -- this may run into bignums, but
173 ;; we probably should flip it into null then for efficiency's sake...
174 (char-pos nil
:type
(or unsigned-byte null
))
175 ;; T if input is waiting on FD. :EOF if we hit EOF.
176 (listen nil
:type
(member nil t
:eof
))
180 (ibuf nil
:type
(or buffer null
))
183 (obuf nil
:type
(or buffer null
))
185 ;; output flushed, but not written due to non-blocking io?
188 ;; timeout specified for this stream as seconds or NIL if none
189 (timeout nil
:type
(or single-float null
))
191 ;; Defaulted pathname used to open this stream (returned by PATHNAME)
192 (pathname nil
:type
(or pathname null
))
193 (external-format :default
)
194 (output-bytes #'ill-out
:type function
)
195 ;; Pathname of the file actually associated with the stream (used by
197 (truename nil
:type
(or pathname null
))
198 ;; If it's built with :OPEN-LAZY-FILE-DISPOSITION, for openings that
199 ;; create fresh files, the altname is the truename the file will
200 ;; have after a non-aborting CLOSE; if it's built without
201 ;; :OPEN-LAZY-FILE-DISPOSITION, the altname is the intermediate name of
202 ;; the old file for openings that replace an existing file.
203 (altname nil
:type
(or pathname null
))
204 ;; Actions to take after closing the descriptor (mostly side effects
205 ;; on the file system). If it's NIL, no actions will be taken.
206 (after-close nil
:type
(or function null
))
208 (owner-pid (sb!unix
:unix-getpid
) :type
(or null integer
))
209 ; #!+win32-uses-file-handles
210 ;; Win32 socket handles need some extra metadata for event
212 ; (events nil :type (or nil fixnum))
215 (def!method print-object
((fd-stream fd-stream
) stream
)
216 (declare (type stream stream
))
217 (print-unreadable-object (fd-stream stream
:type t
:identity t
)
218 (cond ((fd-stream-truename fd-stream
)
219 (format stream
"for file ~A" (fd-stream-truename fd-stream
)))
220 ((fd-stream-name fd-stream
)
221 (format stream
"for ~S" (fd-stream-name fd-stream
)))
223 (format stream
"for descriptor ~D" (fd-stream-fd fd-stream
))))
224 (format stream
"~:[ (stream is closed)~;~]"
225 (open-stream-p fd-stream
))))
227 ;;;; OS file device wrapper functions. For now, only use the win32
228 ;;;; API in case :WIN32-USES-FILE-HANDLES is in the target features.
229 ;;;; These functions are meant to have the API that the SB-UNIX
230 ;;;; bindings do: returning a true value for success, NIL and an error
231 ;;;; code for failure. The success value might be meaningful, or
232 ;;;; might not (e.g., for OS-CLOSE). The error codes are
233 ;;;; platform-specific; the error signaling machinery
234 ;;;; (SIMPLE-STREAM-PERROR, SIMPLE-FILE-PERROR) are responsible for
235 ;;;; turning these codes into messages or types.
237 (defun os-read (device buffer length
)
238 #!-win32-uses-file-handles
239 (sb!unix
:unix-read device buffer length
)
240 #!+win32-uses-file-handles
241 (sb!win32
:read-file device buffer length
))
243 (defun os-write (device buffer offset count
)
244 #!-win32-uses-file-handles
245 (sb!unix
:unix-write device buffer offset count
)
246 #!+win32-uses-file-handles
247 (sb!win32
:write-file device buffer offset count
))
249 (defun os-close (device)
250 #!-win32-uses-file-handles
251 (sb!unix
:unix-close device
)
252 #!+win32-uses-file-handles
253 (sb!win32
:close-handle device
))
255 (defun os-seek (device position whence
)
256 "Reposition the file pointer for DEVICE using POSITION and
257 WHENCE. WHENCE must be one of :START, :END, or T (meaning
258 relative to the current position)."
259 #!-win32-uses-file-handles
260 (sb!unix
:unix-lseek device position
262 (:start sb
!unix
:l_set
)
264 (:end sb
!unix
:l_xtnd
)))
265 #!+win32-uses-file-handles
266 (sb!win32
:set-file-pointer
267 device
(ldb (byte 32 0) position
) (ldb (byte 32 32) position
)
269 (:start sb
!win32
:file_begin
)
270 (t sb
!win32
:file_current
)
271 (:end sb
!win32
:file_end
))))
273 (defun os-file-length (device)
274 #!-win32-uses-file-handles
275 ;; FIXME: the wrapped_stat structure should really die. In this
276 ;; case, replacing it with a function that took an fd and returned
277 ;; the size would suffice.
278 (nth-value 8 (sb!unix
:unix-fstat device
))
279 #!+win32-uses-file-handles
280 (sb!win32
:get-file-size device
))
282 ;;; In order to not go bonkers trying to make POSIX open(2) and Win32
283 ;;; CreateFile() look similar, we invent the following internal API:
284 ;;; we'll use a lightweight structure, OS-OPEN-ARGUMENTS, containing
285 ;;; everything to be passed to open() or CreateFile() other than the
286 ;;; filename. The constructor, MAKE-OS-OPEN-ARGUMENTS, takes keywords
287 ;;; and &ALLOW-OTHER-KEYS, so that we can call the constructor on
288 ;;; whatever arguments OPEN receives; and there's a merging operation
289 ;;; that produces a new OS-OPEN-ARGUMENTS structure using
290 ;;; component-wise replacement rules like a CLtL1ish MERGE-PATHNAMES.
291 ;;; (So to make the following idea work, NIL must /never/ be a
292 ;;; meaningful argument to an opening syscall.) For the most part,
293 ;;; this means that most of the code can pass an opaque thing down the
296 ;; FIXME, maybe: I tried having this be a MACROLET, but the compiler
297 ;; complained that the lexical environment was too hairy to define the
298 ;; DEFSTRUCT accessors inside the MACROLET. Shrug.
299 (defmacro define-unnamed-list-struct
(name (&rest slot-names
))
300 (let ((strict-constructor (read-from-string (format nil
"%MAKE-~A" name
)))
301 (loose-constructor (read-from-string (format nil
"MAKE-~A" name
))))
302 `(progn (defstruct (,name
(:type list
) (:constructor
,strict-constructor
))
304 (defun ,loose-constructor
305 (&key
,@slot-names
&allow-other-keys
)
306 (list ,@slot-names
)))))
308 (define-unnamed-list-struct os-open-arguments
309 #!-win32-uses-file-handles
311 #!+win32-uses-file-handles
312 (desired-access share-mode security-attributes creation-disposition
313 flags-and-attributes template-file
))
316 ;; Unlike *DEFAULT-PATHNAME-DEFAULTS*, this should not be rebound
317 ;; anyplace. Explanations of these defaults: on both Unix and
318 ;; Windows, the defaults will open a file for reading only, and won't
319 ;; create a file where one doesn't exist. The other defaults have to
320 ;; do with metadata on a newly created file: on Unix, we are maximally
321 ;; permissive (but remember the umask); on Windows, everything gets
322 ;; defaulted in the file system.
323 (defvar *default-os-open-arguments-defaults
*
324 #!-win32-uses-file-handles
325 (%make-os-open-arguments
:flags sb
!unix
:o_rdonly
:mode
#o666
)
326 #!+win32-uses-file-handles
327 (%make-os-open-arguments
:desired-access sb
!win32
:generic_read
329 :security-attributes
0
330 :creation-disposition sb
!win32
:open_existing
331 :flags-and-attributes
0
333 "Default arguments to the operating system's file opening operation.")
335 (defun merge-os-open-arguments
336 (args &optional
(defaults *default-os-open-arguments-defaults
*))
337 (assert (= (length args
) (length *default-os-open-arguments-defaults
*)))
338 (mapcar (lambda (x y
) (or x y
)) args defaults
))
340 (defun os-open (filename os-open-arguments
)
341 (let ((args (merge-os-open-arguments os-open-arguments
)))
342 #!-win32-uses-file-handles
343 (destructuring-bind (flags mode
) args
344 (sb!unix
:unix-open filename flags mode
))
345 #!+win32-uses-file-handles
347 (access sharemode attributes disposition flags template
) args
348 (sb!win32
:create-file
349 filename access sharemode attributes disposition flags template
))))
351 ;;;; CORE OUTPUT FUNCTIONS
353 ;;; Buffer the section of THING delimited by START and END by copying
354 ;;; to output buffer(s) of stream.
355 (defun buffer-output (stream thing start end
)
356 (declare (index start end
))
358 (error ":END before :START!"))
360 ;; Copy bytes from THING to buffers.
361 (flet ((copy-to-buffer (buffer tail count
)
362 (declare (buffer buffer
) (index tail count
))
364 (let ((sap (buffer-sap buffer
)))
367 (system-area-ub8-copy thing start sap tail count
))
368 ((simple-unboxed-array (*))
369 (copy-ub8-to-system-area thing start sap tail count
))))
370 ;; Not INCF! If another thread has moved tail from under
371 ;; us, we don't want to accidentally increment tail
372 ;; beyond buffer-length.
373 (setf (buffer-tail buffer
) (+ count tail
))
376 ;; First copy is special: the buffer may already contain
377 ;; something, or be even full.
378 (let* ((obuf (fd-stream-obuf stream
))
379 (tail (buffer-tail obuf
))
380 (space (- (buffer-length obuf
) tail
)))
382 (copy-to-buffer obuf tail
(min space
(- end start
)))
383 (go :more-output-p
)))
385 ;; Later copies should always have an empty buffer, since
386 ;; they are freshly flushed, but if another thread is
387 ;; stomping on the same buffer that might not be the case.
388 (let* ((obuf (flush-output-buffer stream
))
389 (tail (buffer-tail obuf
))
390 (space (- (buffer-length obuf
) tail
)))
391 (copy-to-buffer obuf tail
(min space
(- end start
))))
394 (go :flush-and-fill
))))))
396 ;;; Flush the current output buffer of the stream, ensuring that the
397 ;;; new buffer is empty. Returns (for convenience) the new output
398 ;;; buffer -- which may or may not be EQ to the old one. If the is no
399 ;;; queued output we try to write the buffer immediately -- otherwise
400 ;;; we queue it for later.
401 (defun flush-output-buffer (stream)
402 (let ((obuf (fd-stream-obuf stream
)))
404 (let ((head (buffer-head obuf
))
405 (tail (buffer-tail obuf
)))
406 (cond ((eql head tail
)
407 ;; Buffer is already empty -- just ensure that is is
408 ;; set to zero as well.
410 ((fd-stream-output-queue stream
)
411 ;; There is already stuff on the queue -- go directly
414 (%queue-and-replace-output-buffer stream
))
416 ;; Try a non-blocking write, queue whatever is left over.
418 (synchronize-stream-output stream
)
419 (let ((length (- tail head
)))
420 (multiple-value-bind (count errno
)
421 (os-write (fd-stream-fd stream
) (buffer-sap obuf
)
423 (cond ((eql count length
)
424 ;; Complete write -- we can use the same buffer.
427 ;; Partial write -- update buffer status and queue.
428 ;; Do not use INCF! Another thread might have moved
430 (setf (buffer-head obuf
) (+ count head
))
431 (%queue-and-replace-output-buffer stream
))
433 ((eql errno sb
!unix
:ewouldblock
)
435 (%queue-and-replace-output-buffer stream
))
437 (simple-stream-perror "Couldn't write to ~s"
438 stream errno
)))))))))))
440 ;;; Helper for FLUSH-OUTPUT-BUFFER -- returns the new buffer.
441 (defun %queue-and-replace-output-buffer
(stream)
442 (let ((queue (fd-stream-output-queue stream
))
443 (later (list (or (fd-stream-obuf stream
) (bug "Missing obuf."))))
445 ;; Important: before putting the buffer on queue, give the stream
446 ;; a new one. If we get an interrupt and unwind losing the buffer
447 ;; is relatively OK, but having the same buffer in two places
449 (setf (fd-stream-obuf stream
) new
)
453 (setf (fd-stream-output-queue stream
) later
)))
454 (unless (fd-stream-handler stream
)
455 (setf (fd-stream-handler stream
)
456 (add-fd-handler (fd-stream-fd stream
)
459 (declare (ignore fd
))
460 (write-output-from-queue stream
)))))
463 ;;; This is called by the FD-HANDLER for the stream when output is
465 (defun write-output-from-queue (stream)
466 (synchronize-stream-output stream
)
470 (let* ((buffer (pop (fd-stream-output-queue stream
)))
471 (head (buffer-head buffer
))
472 (length (- (buffer-tail buffer
) head
)))
473 (declare (index head length
))
475 (multiple-value-bind (count errno
)
476 (os-write (fd-stream-fd stream
) (buffer-sap buffer
) head length
)
477 (cond ((eql count length
)
478 ;; Complete write, see if we can do another right
479 ;; away, or remove the handler if we're done.
480 (release-buffer buffer
)
481 (cond ((fd-stream-output-queue stream
)
485 (let ((handler (fd-stream-handler stream
)))
487 (setf (fd-stream-handler stream
) nil
)
488 (remove-fd-handler handler
)))))
490 ;; Partial write. Update buffer status and requeue.
491 (aver (< count length
))
492 ;; Do not use INCF! Another thread might have moved head.
493 (setf (buffer-head buffer
) (+ head count
))
494 (push buffer
(fd-stream-output-queue stream
)))
496 ;; We tried to do multiple writes, and finally our
497 ;; luck ran out. Requeue.
498 (push buffer
(fd-stream-output-queue stream
)))
500 ;; Could not write on the first try at all!
502 (simple-stream-perror "Couldn't write to ~S." stream errno
)
504 (if (= errno sb
!unix
:ewouldblock
)
505 (bug "Unexpected blocking in WRITE-OUTPUT-FROM-QUEUE.")
506 (simple-stream-perror "Couldn't write to ~S"
510 ;;; Try to write THING directly to STREAM without buffering, if
511 ;;; possible. If direct write doesn't happen, buffer.
512 (defun write-or-buffer-output (stream thing start end
)
513 (declare (index start end
))
514 (cond ((fd-stream-output-queue stream
)
515 (buffer-output stream thing start end
))
517 (error ":END before :START!"))
519 (let ((length (- end start
)))
520 (synchronize-stream-output stream
)
521 (multiple-value-bind (count errno
)
522 (os-write (fd-stream-fd stream
) thing start length
)
523 (cond ((eql count length
)
524 ;; Complete write -- done!
527 (aver (< count length
))
528 ;; Partial write -- buffer the rest.
529 (buffer-output stream thing
(+ start count
) end
))
531 ;; Could not write -- buffer or error.
533 (simple-stream-perror "couldn't write to ~s" stream errno
)
535 (if (= errno sb
!unix
:ewouldblock
)
536 (buffer-output stream thing start end
)
537 (simple-stream-perror "couldn't write to ~s" stream errno
)))))))))
539 ;;; Deprecated -- can go away after 1.1 or so. Deprecated because
540 ;;; this is not something we want to export. Nikodemus thinks the
541 ;;; right thing is to support a low-level non-stream like IO layer,
542 ;;; akin to java.nio.
543 (defun output-raw-bytes (stream thing
&optional start end
)
544 (write-or-buffer-output stream thing
(or start
0) (or end
(length thing
))))
546 (define-compiler-macro output-raw-bytes
(stream thing
&optional start end
)
547 (deprecation-warning 'output-raw-bytes
)
548 (let ((x (gensym "THING")))
550 (write-or-buffer-output ,stream
,x
(or ,start
0) (or ,end
(length ,x
))))))
552 ;;;; output routines and related noise
554 (defvar *output-routines
* ()
556 "List of all available output routines. Each element is a list of the
557 element-type output, the kind of buffering, the function name, and the number
558 of bytes per element.")
560 ;;; common idioms for reporting low-level stream and file problems
561 (defun simple-stream-perror (note-format stream errno
)
562 (error 'simple-stream-error
564 :format-control
"~@<~?: ~2I~_~A~:>"
566 (list note-format
(list stream
)
567 #!+unix
(strerror errno
)
568 #!+win32
(sb!win32
:get-last-error-message errno
))))
570 (defun file-error-type (error-code)
572 (#!+unix
#.sb
!unix
:enoent
#!+win32
#.sb
!win32
:error_file_not_found
573 'file-does-not-exist
)
574 (#!+unix
#.sb
!unix
:eexist
575 ;; What's the difference between ERROR_FILE_EXISTS and
576 ;; ERROR_ALREADY_EXISTS? AFAICT, one hundred and three.
577 #!+win32
#.sb
!win32
:error_file_exists
578 #!+win32
#.sb
!win32
:error_already_exists
580 (otherwise 'simple-file-error
)))
582 (defun simple-file-perror (note-format pathname errno
)
583 (error (file-error-type errno
)
585 :format-control
"~@<~?: ~2I~_~A~:>"
587 (list note-format
(list pathname
)
588 #!+unix
(strerror errno
)
589 #!+win32
(sb!win32
:get-last-error-message errno
))))
591 (defun stream-decoding-error (stream octets
)
592 (error 'stream-decoding-error
594 ;; FIXME: dunno how to get at OCTETS currently, or even if
595 ;; that's the right thing to report.
597 (defun stream-encoding-error (stream code
)
598 (error 'stream-encoding-error
602 (defun c-string-encoding-error (external-format code
)
603 (error 'c-string-encoding-error
604 :external-format external-format
607 (defun c-string-decoding-error (external-format octets
)
608 (error 'c-string-decoding-error
609 :external-format external-format
612 ;;; Returning true goes into end of file handling, false will enter another
613 ;;; round of input buffer filling followed by re-entering character decode.
614 (defun stream-decoding-error-and-handle (stream octet-count
)
616 (stream-decoding-error stream
617 (let* ((buffer (fd-stream-ibuf stream
))
618 (sap (buffer-sap buffer
))
619 (head (buffer-head buffer
)))
620 (loop for i from
0 below octet-count
621 collect
(sap-ref-8 sap
(+ head i
)))))
623 :report
(lambda (stream)
625 "~@<Attempt to resync the stream at a character ~
626 character boundary and continue.~@:>"))
627 (fd-stream-resync stream
)
629 (force-end-of-file ()
630 :report
(lambda (stream)
631 (format stream
"~@<Force an end of file.~@:>"))
634 (defun stream-encoding-error-and-handle (stream code
)
636 (stream-encoding-error stream code
)
638 :report
(lambda (stream)
639 (format stream
"~@<Skip output of this character.~@:>"))
640 (throw 'output-nothing nil
))))
642 (defun external-format-encoding-error (stream code
)
644 (stream-encoding-error-and-handle stream code
)
645 (c-string-encoding-error stream code
)))
647 (defun external-format-decoding-error (stream octet-count
)
649 (stream-decoding-error stream octet-count
)
650 (c-string-decoding-error stream octet-count
)))
652 (defun synchronize-stream-output (stream)
653 ;; If we're reading and writing on the same file, flush buffered
654 ;; input and rewind file position accordingly.
655 (unless (fd-stream-dual-channel-p stream
)
656 (let ((adjust (nth-value 1 (flush-input-buffer stream
))))
657 (unless (eql 0 adjust
)
658 (os-seek (fd-stream-fd stream
) (- adjust
) t
)))))
660 (defun fd-stream-output-finished-p (stream)
661 (let ((obuf (fd-stream-obuf stream
)))
663 (and (zerop (buffer-tail obuf
))
664 (not (fd-stream-output-queue stream
))))))
666 (defmacro output-wrapper
/variable-width
((stream size buffering restart
)
668 (let ((stream-var (gensym "STREAM")))
669 `(let* ((,stream-var
,stream
)
670 (obuf (fd-stream-obuf ,stream-var
))
671 (tail (buffer-tail obuf
))
673 ,(unless (eq (car buffering
) :none
)
674 `(when (<= (buffer-length obuf
) (+ tail size
))
675 (setf obuf
(flush-output-buffer ,stream-var
)
676 tail
(buffer-tail obuf
))))
677 ,(unless (eq (car buffering
) :none
)
678 ;; FIXME: Why this here? Doesn't seem necessary.
679 `(synchronize-stream-output ,stream-var
))
681 `(catch 'output-nothing
683 (setf (buffer-tail obuf
) (+ tail size
)))
686 (setf (buffer-tail obuf
) (+ tail size
))))
687 ,(ecase (car buffering
)
689 `(flush-output-buffer ,stream-var
))
691 `(when (eql byte
#\Newline
)
692 (flush-output-buffer ,stream-var
)))
696 (defmacro output-wrapper
((stream size buffering restart
) &body body
)
697 (let ((stream-var (gensym "STREAM")))
698 `(let* ((,stream-var
,stream
)
699 (obuf (fd-stream-obuf ,stream-var
))
700 (tail (buffer-tail obuf
)))
701 ,(unless (eq (car buffering
) :none
)
702 `(when (<= (buffer-length obuf
) (+ tail
,size
))
703 (setf obuf
(flush-output-buffer ,stream-var
)
704 tail
(buffer-tail obuf
))))
705 ;; FIXME: Why this here? Doesn't seem necessary.
706 ,(unless (eq (car buffering
) :none
)
707 `(synchronize-stream-output ,stream-var
))
709 `(catch 'output-nothing
711 (setf (buffer-tail obuf
) (+ tail
,size
)))
714 (setf (buffer-tail obuf
) (+ tail
,size
))))
715 ,(ecase (car buffering
)
717 `(flush-output-buffer ,stream-var
))
719 `(when (eql byte
#\Newline
)
720 (flush-output-buffer ,stream-var
)))
724 (defmacro def-output-routines
/variable-width
725 ((name-fmt size restart external-format
&rest bufferings
)
727 (declare (optimize (speed 1)))
732 (intern (format nil name-fmt
(string (car buffering
))))))
734 (defun ,function
(stream byte
)
735 (declare (ignorable byte
))
736 (output-wrapper/variable-width
(stream ,size
,buffering
,restart
)
738 (setf *output-routines
*
739 (nconc *output-routines
*
747 (cdr buffering
)))))))
750 ;;; Define output routines that output numbers SIZE bytes long for the
751 ;;; given bufferings. Use BODY to do the actual output.
752 (defmacro def-output-routines
((name-fmt size restart
&rest bufferings
)
754 (declare (optimize (speed 1)))
759 (intern (format nil name-fmt
(string (car buffering
))))))
761 (defun ,function
(stream byte
)
762 (output-wrapper (stream ,size
,buffering
,restart
)
764 (setf *output-routines
*
765 (nconc *output-routines
*
773 (cdr buffering
)))))))
776 ;;; FIXME: is this used anywhere any more?
777 (def-output-routines ("OUTPUT-CHAR-~A-BUFFERED"
783 (if (eql byte
#\Newline
)
784 (setf (fd-stream-char-pos stream
) 0)
785 (incf (fd-stream-char-pos stream
)))
786 (setf (sap-ref-8 (buffer-sap obuf
) tail
)
789 (def-output-routines ("OUTPUT-UNSIGNED-BYTE-~A-BUFFERED"
792 (:none
(unsigned-byte 8))
793 (:full
(unsigned-byte 8)))
794 (setf (sap-ref-8 (buffer-sap obuf
) tail
)
797 (def-output-routines ("OUTPUT-SIGNED-BYTE-~A-BUFFERED"
800 (:none
(signed-byte 8))
801 (:full
(signed-byte 8)))
802 (setf (signed-sap-ref-8 (buffer-sap obuf
) tail
)
805 (def-output-routines ("OUTPUT-UNSIGNED-SHORT-~A-BUFFERED"
808 (:none
(unsigned-byte 16))
809 (:full
(unsigned-byte 16)))
810 (setf (sap-ref-16 (buffer-sap obuf
) tail
)
813 (def-output-routines ("OUTPUT-SIGNED-SHORT-~A-BUFFERED"
816 (:none
(signed-byte 16))
817 (:full
(signed-byte 16)))
818 (setf (signed-sap-ref-16 (buffer-sap obuf
) tail
)
821 (def-output-routines ("OUTPUT-UNSIGNED-LONG-~A-BUFFERED"
824 (:none
(unsigned-byte 32))
825 (:full
(unsigned-byte 32)))
826 (setf (sap-ref-32 (buffer-sap obuf
) tail
)
829 (def-output-routines ("OUTPUT-SIGNED-LONG-~A-BUFFERED"
832 (:none
(signed-byte 32))
833 (:full
(signed-byte 32)))
834 (setf (signed-sap-ref-32 (buffer-sap obuf
) tail
)
837 #+#.
(cl:if
(cl:= sb
!vm
:n-word-bits
64) '(and) '(or))
839 (def-output-routines ("OUTPUT-UNSIGNED-LONG-LONG-~A-BUFFERED"
842 (:none
(unsigned-byte 64))
843 (:full
(unsigned-byte 64)))
844 (setf (sap-ref-64 (buffer-sap obuf
) tail
)
846 (def-output-routines ("OUTPUT-SIGNED-LONG-LONG-~A-BUFFERED"
849 (:none
(signed-byte 64))
850 (:full
(signed-byte 64)))
851 (setf (signed-sap-ref-64 (buffer-sap obuf
) tail
)
854 ;;; the routine to use to output a string. If the stream is
855 ;;; unbuffered, slam the string down the file descriptor, otherwise
856 ;;; use OUTPUT-RAW-BYTES to buffer the string. Update charpos by
857 ;;; checking to see where the last newline was.
858 (defun fd-sout (stream thing start end
)
859 (declare (type fd-stream stream
) (type string thing
))
860 (let ((start (or start
0))
861 (end (or end
(length (the vector thing
)))))
862 (declare (fixnum start end
))
864 (string-dispatch (simple-base-string
866 (simple-array character
(*))
869 (position #\newline thing
:from-end t
870 :start start
:end end
))))
871 (if (and (typep thing
'base-string
)
872 (eq (fd-stream-external-format stream
) :latin-1
))
873 (ecase (fd-stream-buffering stream
)
875 (buffer-output stream thing start end
))
877 (buffer-output stream thing start end
)
879 (flush-output-buffer stream
)))
881 (write-or-buffer-output stream thing start end
)))
882 (ecase (fd-stream-buffering stream
)
883 (:full
(funcall (fd-stream-output-bytes stream
)
884 stream thing nil start end
))
885 (:line
(funcall (fd-stream-output-bytes stream
)
886 stream thing last-newline start end
))
887 (:none
(funcall (fd-stream-output-bytes stream
)
888 stream thing t start end
))))
890 (setf (fd-stream-char-pos stream
) (- end last-newline
1))
891 (incf (fd-stream-char-pos stream
) (- end start
))))))
893 (defvar *external-formats
* ()
895 "List of all available external formats. Each element is a list of the
896 element-type, string input function name, character input function name,
897 and string output function name.")
899 (defun get-external-format (external-format)
900 (dolist (entry *external-formats
*)
901 (when (member external-format
(first entry
))
904 (defun get-external-format-function (external-format index
)
905 (let ((entry (get-external-format external-format
)))
906 (when entry
(nth index entry
))))
908 ;;; Find an output routine to use given the type and buffering. Return
909 ;;; as multiple values the routine, the real type transfered, and the
910 ;;; number of bytes per element.
911 (defun pick-output-routine (type buffering
&optional external-format
)
912 (when (subtypep type
'character
)
913 (let ((entry (get-external-format external-format
)))
915 (return-from pick-output-routine
916 (values (symbol-function (nth (ecase buffering
923 (symbol-function (fourth entry
))
924 (first (first entry
)))))))
925 (dolist (entry *output-routines
*)
926 (when (and (subtypep type
(first entry
))
927 (eq buffering
(second entry
))
928 (or (not (fifth entry
))
929 (eq external-format
(fifth entry
))))
930 (return-from pick-output-routine
931 (values (symbol-function (third entry
))
934 ;; KLUDGE: dealing with the buffering here leads to excessive code
937 ;; KLUDGE: also see comments in PICK-INPUT-ROUTINE
938 (loop for i from
40 by
8 to
1024 ; ARB (KLUDGE)
939 if
(subtypep type
`(unsigned-byte ,i
))
940 do
(return-from pick-output-routine
944 (lambda (stream byte
)
945 (output-wrapper (stream (/ i
8) (:none
) nil
)
946 (loop for j from
0 below
(/ i
8)
947 do
(setf (sap-ref-8 (buffer-sap obuf
)
949 (ldb (byte 8 (- i
8 (* j
8))) byte
))))))
951 (lambda (stream byte
)
952 (output-wrapper (stream (/ i
8) (:full
) nil
)
953 (loop for j from
0 below
(/ i
8)
954 do
(setf (sap-ref-8 (buffer-sap obuf
)
956 (ldb (byte 8 (- i
8 (* j
8))) byte
)))))))
959 (loop for i from
40 by
8 to
1024 ; ARB (KLUDGE)
960 if
(subtypep type
`(signed-byte ,i
))
961 do
(return-from pick-output-routine
965 (lambda (stream byte
)
966 (output-wrapper (stream (/ i
8) (:none
) nil
)
967 (loop for j from
0 below
(/ i
8)
968 do
(setf (sap-ref-8 (buffer-sap obuf
)
970 (ldb (byte 8 (- i
8 (* j
8))) byte
))))))
972 (lambda (stream byte
)
973 (output-wrapper (stream (/ i
8) (:full
) nil
)
974 (loop for j from
0 below
(/ i
8)
975 do
(setf (sap-ref-8 (buffer-sap obuf
)
977 (ldb (byte 8 (- i
8 (* j
8))) byte
)))))))
981 ;;;; input routines and related noise
983 ;;; a list of all available input routines. Each element is a list of
984 ;;; the element-type input, the function name, and the number of bytes
986 (defvar *input-routines
* ())
988 ;;; Return whether a primitive partial read operation on STREAM's FD
989 ;;; would (probably) block. Signal a `simple-stream-error' if the
990 ;;; system call implementing this operation fails.
992 ;;; It is "may" instead of "would" because "would" is not quite
993 ;;; correct on win32. However, none of the places that use it require
994 ;;; further assurance than "may" versus "will definitely not".
995 (defun sysread-may-block-p (stream)
996 #!+(and win32
(not win32-uses-file-handles
))
997 ;; This answers T at EOF on win32, I think.
998 (not (sb!win32
:fd-listen
(fd-stream-fd stream
)))
999 #!+(and win32 win32-uses-file-handles
)
1000 (not (sb!win32
:handle-listen
(fd-stream-fd stream
)))
1002 (sb!unix
:with-restarted-syscall
(count errno
)
1003 (sb!alien
:with-alien
((read-fds (sb!alien
:struct sb
!unix
:fd-set
)))
1004 (sb!unix
:fd-zero read-fds
)
1005 (sb!unix
:fd-set
(fd-stream-fd stream
) read-fds
)
1006 (sb!unix
:unix-fast-select
(1+ (fd-stream-fd stream
))
1007 (sb!alien
:addr read-fds
)
1013 (simple-stream-perror "couldn't check whether ~S is readable"
1017 ;;; If the read would block wait (using SERVE-EVENT) till input is available,
1018 ;;; then fill the input buffer, and return the number of bytes read. Throws
1019 ;;; to EOF-INPUT-CATCHER if the eof was reached.
1020 (defun refill-input-buffer (stream)
1021 (let ((fd (fd-stream-fd stream
))
1024 (declare (dynamic-extent fd errno count
))
1026 ;; Check for blocking input before touching the stream, as if
1027 ;; we happen to wait we are liable to be interrupted, and the
1028 ;; interrupt handler may use the same stream.
1029 (if (sysread-may-block-p stream
)
1030 (go :wait-for-input
)
1032 ;; These (:CLOSED-FLAME and :READ-ERROR) tags are here so what
1033 ;; we can signal errors outside the WITHOUT-INTERRUPTS.
1035 (closed-flame stream
)
1037 (simple-stream-perror "couldn't read from ~S" stream errno
)
1039 ;; This tag is here so we can unwind outside the WITHOUT-INTERRUPTS
1040 ;; to wait for input if read tells us EWOULDBLOCK.
1041 (unless (wait-until-fd-usable fd
:input
(fd-stream-timeout stream
))
1042 (signal-timeout 'io-timeout
:stream stream
:direction
:read
1043 :seconds
(fd-stream-timeout stream
)))
1045 ;; Since the read should not block, we'll disable the
1046 ;; interrupts here, so that we don't accidentally unwind and
1047 ;; leave the stream in an inconsistent state.
1049 ;; Execute the nlx outside without-interrupts to ensure the
1050 ;; resulting thunk is stack-allocatable.
1051 ((lambda (return-reason)
1052 (ecase return-reason
1053 ((nil)) ; fast path normal cases
1054 ((:wait-for-input
) (go :wait-for-input
))
1055 ((:closed-flame
) (go :closed-flame
))
1056 ((:read-error
) (go :read-error
))))
1058 ;; Check the buffer: if it is null, then someone has closed
1059 ;; the stream from underneath us. This is not ment to fix
1060 ;; multithreaded races, but to deal with interrupt handlers
1061 ;; closing the stream.
1064 (let* ((ibuf (or (fd-stream-ibuf stream
) (return :closed-flame
)))
1065 (sap (buffer-sap ibuf
))
1066 (length (buffer-length ibuf
))
1067 (head (buffer-head ibuf
))
1068 (tail (buffer-tail ibuf
)))
1069 (declare (index length head tail
)
1071 (unless (zerop head
)
1072 (cond ((eql head tail
)
1073 ;; Buffer is empty, but not at yet reset -- make it so.
1076 (reset-buffer ibuf
))
1078 ;; Buffer has things in it, but they are not at the
1079 ;; head -- move them there.
1080 (let ((n (- tail head
)))
1081 (system-area-ub8-copy sap head sap
0 n
)
1083 (buffer-head ibuf
) head
1085 (buffer-tail ibuf
) tail
)))))
1086 (setf (fd-stream-listen stream
) nil
)
1087 (setf (values count errno
)
1088 (os-read fd
(sap+ sap tail
) (- length tail
)))
1089 (cond ((or (and (integerp count
) (zerop count
))
1090 ;; Evidently, windows doesn't give you a
1091 ;; zero-length read for a closed pipe, but
1093 #!+win32-uses-file-handles
1095 (eql errno sb
!win32
:error_broken_pipe
)))
1096 (setf (fd-stream-listen stream
) :eof
)
1097 (/show0
"THROWing EOF-INPUT-CATCHER")
1098 (throw 'eof-input-catcher nil
))
1101 (return :read-error
)
1103 (if (eql errno sb
!unix
:ewouldblock
)
1104 (return :wait-for-input
)
1105 (return :read-error
)))
1107 ;; Success! (Do not use INCF, for sake of other threads.)
1108 (setf (buffer-tail ibuf
) (+ count tail
))))))))))
1111 ;;; Make sure there are at least BYTES number of bytes in the input
1112 ;;; buffer. Keep calling REFILL-INPUT-BUFFER until that condition is met.
1113 (defmacro input-at-least
(stream bytes
)
1114 (let ((stream-var (gensym "STREAM"))
1115 (bytes-var (gensym "BYTES"))
1116 (buffer-var (gensym "IBUF")))
1117 `(let* ((,stream-var
,stream
)
1119 (,buffer-var
(fd-stream-ibuf ,stream-var
)))
1121 (when (>= (- (buffer-tail ,buffer-var
)
1122 (buffer-head ,buffer-var
))
1125 (refill-input-buffer ,stream-var
)))))
1127 (defmacro input-wrapper
/variable-width
((stream bytes eof-error eof-value
)
1129 (let ((stream-var (gensym "STREAM"))
1130 (retry-var (gensym "RETRY"))
1131 (element-var (gensym "ELT")))
1132 `(let* ((,stream-var
,stream
)
1133 (ibuf (fd-stream-ibuf ,stream-var
))
1135 (if (fd-stream-unread ,stream-var
)
1137 (fd-stream-unread ,stream-var
)
1138 (setf (fd-stream-unread ,stream-var
) nil
)
1139 (setf (fd-stream-listen ,stream-var
) nil
))
1140 (let ((,element-var nil
)
1141 (decode-break-reason nil
))
1142 (do ((,retry-var t
))
1145 (catch 'eof-input-catcher
1146 (setf decode-break-reason
1147 (block decode-break-reason
1148 (input-at-least ,stream-var
1)
1149 (let* ((byte (sap-ref-8 (buffer-sap ibuf
)
1150 (buffer-head ibuf
))))
1151 (declare (ignorable byte
))
1153 (input-at-least ,stream-var size
)
1154 (setq ,element-var
(locally ,@read-forms
))
1155 (setq ,retry-var nil
))
1157 (when decode-break-reason
1158 (stream-decoding-error-and-handle stream
1159 decode-break-reason
))
1161 (let ((octet-count (- (buffer-tail ibuf
)
1162 (buffer-head ibuf
))))
1163 (when (or (zerop octet-count
)
1164 (and (not ,element-var
)
1165 (not decode-break-reason
)
1166 (stream-decoding-error-and-handle
1167 stream octet-count
)))
1168 (setq ,retry-var nil
)))))
1170 (incf (buffer-head ibuf
) size
)
1173 (eof-or-lose ,stream-var
,eof-error
,eof-value
))))))))
1175 ;;; a macro to wrap around all input routines to handle EOF-ERROR noise
1176 (defmacro input-wrapper
((stream bytes eof-error eof-value
) &body read-forms
)
1177 (let ((stream-var (gensym "STREAM"))
1178 (element-var (gensym "ELT")))
1179 `(let* ((,stream-var
,stream
)
1180 (ibuf (fd-stream-ibuf ,stream-var
)))
1181 (if (fd-stream-unread ,stream-var
)
1183 (fd-stream-unread ,stream-var
)
1184 (setf (fd-stream-unread ,stream-var
) nil
)
1185 (setf (fd-stream-listen ,stream-var
) nil
))
1187 (catch 'eof-input-catcher
1188 (input-at-least ,stream-var
,bytes
)
1189 (locally ,@read-forms
))))
1191 (incf (buffer-head (fd-stream-ibuf ,stream-var
)) ,bytes
)
1194 (eof-or-lose ,stream-var
,eof-error
,eof-value
))))))))
1196 (defmacro def-input-routine
/variable-width
(name
1197 (type external-format size sap head
)
1200 (defun ,name
(stream eof-error eof-value
)
1201 (input-wrapper/variable-width
(stream ,size eof-error eof-value
)
1202 (let ((,sap
(buffer-sap ibuf
))
1203 (,head
(buffer-head ibuf
)))
1205 (setf *input-routines
*
1206 (nconc *input-routines
*
1207 (list (list ',type
',name
1 ',external-format
))))))
1209 (defmacro def-input-routine
(name
1210 (type size sap head
)
1213 (defun ,name
(stream eof-error eof-value
)
1214 (input-wrapper (stream ,size eof-error eof-value
)
1215 (let ((,sap
(buffer-sap ibuf
))
1216 (,head
(buffer-head ibuf
)))
1218 (setf *input-routines
*
1219 (nconc *input-routines
*
1220 (list (list ',type
',name
',size nil
))))))
1222 ;;; STREAM-IN routine for reading a string char
1223 (def-input-routine input-character
1224 (character 1 sap head
)
1225 (code-char (sap-ref-8 sap head
)))
1227 ;;; STREAM-IN routine for reading an unsigned 8 bit number
1228 (def-input-routine input-unsigned-8bit-byte
1229 ((unsigned-byte 8) 1 sap head
)
1230 (sap-ref-8 sap head
))
1232 ;;; STREAM-IN routine for reading a signed 8 bit number
1233 (def-input-routine input-signed-8bit-number
1234 ((signed-byte 8) 1 sap head
)
1235 (signed-sap-ref-8 sap head
))
1237 ;;; STREAM-IN routine for reading an unsigned 16 bit number
1238 (def-input-routine input-unsigned-16bit-byte
1239 ((unsigned-byte 16) 2 sap head
)
1240 (sap-ref-16 sap head
))
1242 ;;; STREAM-IN routine for reading a signed 16 bit number
1243 (def-input-routine input-signed-16bit-byte
1244 ((signed-byte 16) 2 sap head
)
1245 (signed-sap-ref-16 sap head
))
1247 ;;; STREAM-IN routine for reading a unsigned 32 bit number
1248 (def-input-routine input-unsigned-32bit-byte
1249 ((unsigned-byte 32) 4 sap head
)
1250 (sap-ref-32 sap head
))
1252 ;;; STREAM-IN routine for reading a signed 32 bit number
1253 (def-input-routine input-signed-32bit-byte
1254 ((signed-byte 32) 4 sap head
)
1255 (signed-sap-ref-32 sap head
))
1257 #+#.
(cl:if
(cl:= sb
!vm
:n-word-bits
64) '(and) '(or))
1259 (def-input-routine input-unsigned-64bit-byte
1260 ((unsigned-byte 64) 8 sap head
)
1261 (sap-ref-64 sap head
))
1262 (def-input-routine input-signed-64bit-byte
1263 ((signed-byte 64) 8 sap head
)
1264 (signed-sap-ref-64 sap head
)))
1266 ;;; Find an input routine to use given the type. Return as multiple
1267 ;;; values the routine, the real type transfered, and the number of
1268 ;;; bytes per element (and for character types string input routine).
1269 (defun pick-input-routine (type &optional external-format
)
1270 (when (subtypep type
'character
)
1271 (dolist (entry *external-formats
*)
1272 (when (member external-format
(first entry
))
1273 (return-from pick-input-routine
1274 (values (symbol-function (third entry
))
1277 (symbol-function (second entry
))
1278 (first (first entry
)))))))
1279 (dolist (entry *input-routines
*)
1280 (when (and (subtypep type
(first entry
))
1281 (or (not (fourth entry
))
1282 (eq external-format
(fourth entry
))))
1283 (return-from pick-input-routine
1284 (values (symbol-function (second entry
))
1287 ;; FIXME: let's do it the hard way, then (but ignore things like
1288 ;; endianness, efficiency, and the necessary coupling between these
1289 ;; and the output routines). -- CSR, 2004-02-09
1290 (loop for i from
40 by
8 to
1024 ; ARB (well, KLUDGE really)
1291 if
(subtypep type
`(unsigned-byte ,i
))
1292 do
(return-from pick-input-routine
1294 (lambda (stream eof-error eof-value
)
1295 (input-wrapper (stream (/ i
8) eof-error eof-value
)
1296 (let ((sap (buffer-sap ibuf
))
1297 (head (buffer-head ibuf
)))
1298 (loop for j from
0 below
(/ i
8)
1302 (sap-ref-8 sap
(+ head j
))))
1303 finally
(return result
)))))
1306 (loop for i from
40 by
8 to
1024 ; ARB (well, KLUDGE really)
1307 if
(subtypep type
`(signed-byte ,i
))
1308 do
(return-from pick-input-routine
1310 (lambda (stream eof-error eof-value
)
1311 (input-wrapper (stream (/ i
8) eof-error eof-value
)
1312 (let ((sap (buffer-sap ibuf
))
1313 (head (buffer-head ibuf
)))
1314 (loop for j from
0 below
(/ i
8)
1318 (sap-ref-8 sap
(+ head j
))))
1319 finally
(return (if (logbitp (1- i
) result
)
1320 (dpb result
(byte i
0) -
1)
1325 ;;; the N-BIN method for FD-STREAMs
1327 ;;; Note that this blocks in UNIX-READ. It is generally used where
1328 ;;; there is a definite amount of reading to be done, so blocking
1329 ;;; isn't too problematical.
1330 (defun fd-stream-read-n-bytes (stream buffer start requested eof-error-p
1331 &aux
(total-copied 0))
1332 (declare (type fd-stream stream
))
1333 (declare (type index start requested total-copied
))
1334 (let ((unread (fd-stream-unread stream
)))
1336 ;; AVERs designed to fail when we have more complicated
1337 ;; character representations.
1338 (aver (typep unread
'base-char
))
1339 (aver (= (fd-stream-element-size stream
) 1))
1340 ;; KLUDGE: this is a slightly-unrolled-and-inlined version of
1343 (system-area-pointer
1344 (setf (sap-ref-8 buffer start
) (char-code unread
)))
1345 ((simple-unboxed-array (*))
1346 (setf (aref buffer start
) unread
)))
1347 (setf (fd-stream-unread stream
) nil
)
1348 (setf (fd-stream-listen stream
) nil
)
1349 (incf total-copied
)))
1352 (let* ((remaining-request (- requested total-copied
))
1353 (ibuf (fd-stream-ibuf stream
))
1354 (head (buffer-head ibuf
))
1355 (tail (buffer-tail ibuf
))
1356 (available (- tail head
))
1357 (n-this-copy (min remaining-request available
))
1358 (this-start (+ start total-copied
))
1359 (this-end (+ this-start n-this-copy
))
1360 (sap (buffer-sap ibuf
)))
1361 (declare (type index remaining-request head tail available
))
1362 (declare (type index n-this-copy
))
1363 ;; Copy data from stream buffer into user's buffer.
1364 (%byte-blt sap head buffer this-start this-end
)
1365 (incf (buffer-head ibuf
) n-this-copy
)
1366 (incf total-copied n-this-copy
)
1367 ;; Maybe we need to refill the stream buffer.
1368 (cond (;; If there were enough data in the stream buffer, we're done.
1369 (eql total-copied requested
)
1370 (return total-copied
))
1371 (;; If EOF, we're done in another way.
1372 (null (catch 'eof-input-catcher
(refill-input-buffer stream
)))
1374 (error 'end-of-file
:stream stream
)
1375 (return total-copied
)))
1376 ;; Otherwise we refilled the stream buffer, so fall
1377 ;; through into another pass of the loop.
1380 (defun fd-stream-resync (stream)
1381 (dolist (entry *external-formats
*)
1382 (when (member (fd-stream-external-format stream
) (first entry
))
1383 (return-from fd-stream-resync
1384 (funcall (symbol-function (eighth entry
)) stream
)))))
1386 (defun get-fd-stream-character-sizer (stream)
1387 (dolist (entry *external-formats
*)
1388 (when (member (fd-stream-external-format stream
) (first entry
))
1389 (return-from get-fd-stream-character-sizer
(ninth entry
)))))
1391 (defun fd-stream-character-size (stream char
)
1392 (let ((sizer (get-fd-stream-character-sizer stream
)))
1393 (when sizer
(funcall sizer char
))))
1395 (defun fd-stream-string-size (stream string
)
1396 (let ((sizer (get-fd-stream-character-sizer stream
)))
1398 (loop for char across string summing
(funcall sizer char
)))))
1400 (defun find-external-format (external-format)
1401 (when external-format
1402 (find external-format
*external-formats
* :test
#'member
:key
#'car
)))
1404 (defun variable-width-external-format-p (ef-entry)
1405 (when (eighth ef-entry
) t
))
1407 (defun bytes-for-char-fun (ef-entry)
1408 (if ef-entry
(symbol-function (ninth ef-entry
)) (constantly 1)))
1410 ;;; FIXME: OAOOM here vrt. *EXTERNAL-FORMAT-FUNCTIONS* in fd-stream.lisp
1411 (defmacro define-external-format
(external-format size output-restart
1413 (let* ((name (first external-format
))
1414 (out-function (symbolicate "OUTPUT-BYTES/" name
))
1415 (format (format nil
"OUTPUT-CHAR-~A-~~A-BUFFERED" (string name
)))
1416 (in-function (symbolicate "FD-STREAM-READ-N-CHARACTERS/" name
))
1417 (in-char-function (symbolicate "INPUT-CHAR/" name
))
1418 (size-function (symbolicate "BYTES-FOR-CHAR/" name
))
1419 (read-c-string-function (symbolicate "READ-FROM-C-STRING/" name
))
1420 (output-c-string-function (symbolicate "OUTPUT-TO-C-STRING/" name
))
1421 (n-buffer (gensym "BUFFER")))
1423 (defun ,size-function
(byte)
1424 (declare (ignore byte
))
1426 (defun ,out-function
(stream string flush-p start end
)
1427 (let ((start (or start
0))
1428 (end (or end
(length string
))))
1429 (declare (type index start end
))
1430 (synchronize-stream-output stream
)
1431 (unless (<= 0 start end
(length string
))
1432 (sequence-bounding-indices-bad-error string start end
))
1435 (let ((obuf (fd-stream-obuf stream
)))
1436 (setf (buffer-tail obuf
)
1437 (string-dispatch (simple-base-string
1439 (simple-array character
(*))
1442 (let ((sap (buffer-sap obuf
))
1443 (len (buffer-length obuf
))
1445 (tail (buffer-tail obuf
)))
1446 (declare (type index tail
)
1447 ;; STRING bounds have already been checked.
1448 (optimize (safety 0)))
1450 (,@(if output-restart
1451 `(catch 'output-nothing
)
1454 ((or (= start end
) (< (- len tail
) 4)))
1455 (let* ((byte (aref string start
))
1456 (bits (char-code byte
)))
1460 ;; Exited from the loop normally
1462 ;; Exited via CATCH. Skip the current character
1463 ;; and try the inner loop again.
1466 (flush-output-buffer stream
)))
1468 (flush-output-buffer stream
))))
1469 (def-output-routines (,format
1475 (if (eql byte
#\Newline
)
1476 (setf (fd-stream-char-pos stream
) 0)
1477 (incf (fd-stream-char-pos stream
)))
1478 (let* ((obuf (fd-stream-obuf stream
))
1479 (bits (char-code byte
))
1480 (sap (buffer-sap obuf
))
1481 (tail (buffer-tail obuf
)))
1483 (defun ,in-function
(stream buffer start requested eof-error-p
1484 &aux
(index start
) (end (+ start requested
)))
1485 (declare (type fd-stream stream
)
1486 (type index start requested index end
)
1488 (simple-array character
(#.
+ansi-stream-in-buffer-length
+))
1490 (let ((unread (fd-stream-unread stream
)))
1492 (setf (aref buffer index
) unread
)
1493 (setf (fd-stream-unread stream
) nil
)
1494 (setf (fd-stream-listen stream
) nil
)
1498 (let* ((ibuf (fd-stream-ibuf stream
))
1499 (head (buffer-head ibuf
))
1500 (tail (buffer-tail ibuf
))
1501 (sap (buffer-sap ibuf
)))
1502 (declare (type index head tail
)
1503 (type system-area-pointer sap
))
1504 ;; Copy data from stream buffer into user's buffer.
1505 (dotimes (i (min (truncate (- tail head
) ,size
)
1507 (declare (optimize speed
))
1508 (let* ((byte (sap-ref-8 sap head
)))
1509 (setf (aref buffer index
) ,in-expr
)
1512 (setf (buffer-head ibuf
) head
)
1513 ;; Maybe we need to refill the stream buffer.
1514 (cond ( ;; If there was enough data in the stream buffer, we're done.
1516 (return (- index start
)))
1517 ( ;; If EOF, we're done in another way.
1518 (null (catch 'eof-input-catcher
(refill-input-buffer stream
)))
1520 (error 'end-of-file
:stream stream
)
1521 (return (- index start
))))
1522 ;; Otherwise we refilled the stream buffer, so fall
1523 ;; through into another pass of the loop.
1525 (def-input-routine ,in-char-function
(character ,size sap head
)
1526 (let ((byte (sap-ref-8 sap head
)))
1528 (defun ,read-c-string-function
(sap element-type
)
1529 (declare (type system-area-pointer sap
)
1530 (type (member character base-char
) element-type
))
1532 (declare (optimize (speed 3) (safety 0)))
1533 (let* ((stream ,name
)
1535 (loop for head of-type index upfrom
0 by
,size
1536 for count of-type index upto
(1- array-dimension-limit
)
1537 for byte
= (sap-ref-8 sap head
)
1538 for char of-type character
= ,in-expr
1539 until
(zerop (char-code char
))
1540 finally
(return count
)))
1541 ;; Inline the common cases
1542 (string (make-string length
:element-type element-type
)))
1543 (declare (ignorable stream
)
1545 (type simple-string string
))
1546 (/show0 before-copy-loop
)
1547 (loop for head of-type index upfrom
0 by
,size
1548 for index of-type index below length
1549 for byte
= (sap-ref-8 sap head
)
1550 for char of-type character
= ,in-expr
1551 do
(setf (aref string index
) char
))
1552 string
))) ;; last loop rewrite to dotimes?
1553 (defun ,output-c-string-function
(string)
1554 (declare (type simple-string string
))
1556 (declare (optimize (speed 3) (safety 0)))
1557 (let* ((length (length string
))
1558 (,n-buffer
(make-array (* (1+ length
) ,size
)
1559 :element-type
'(unsigned-byte 8)))
1562 (declare (type index length tail
))
1563 (with-pinned-objects (,n-buffer
)
1564 (let ((sap (vector-sap ,n-buffer
)))
1565 (declare (system-area-pointer sap
))
1567 (let* ((byte (aref string i
))
1568 (bits (char-code byte
)))
1569 (declare (ignorable byte bits
))
1573 (byte (code-char bits
)))
1574 (declare (ignorable bits byte
))
1577 (setf *external-formats
*
1578 (cons '(,external-format
,in-function
,in-char-function
,out-function
1579 ,@(mapcar #'(lambda (buffering)
1580 (intern (format nil format
(string buffering
))))
1581 '(:none
:line
:full
))
1582 nil
; no resync-function
1583 ,size-function
,read-c-string-function
,output-c-string-function
)
1584 *external-formats
*)))))
1586 (defmacro define-external-format
/variable-width
1587 (external-format output-restart out-size-expr
1588 out-expr in-size-expr in-expr
)
1589 (let* ((name (first external-format
))
1590 (out-function (symbolicate "OUTPUT-BYTES/" name
))
1591 (format (format nil
"OUTPUT-CHAR-~A-~~A-BUFFERED" (string name
)))
1592 (in-function (symbolicate "FD-STREAM-READ-N-CHARACTERS/" name
))
1593 (in-char-function (symbolicate "INPUT-CHAR/" name
))
1594 (resync-function (symbolicate "RESYNC/" name
))
1595 (size-function (symbolicate "BYTES-FOR-CHAR/" name
))
1596 (read-c-string-function (symbolicate "READ-FROM-C-STRING/" name
))
1597 (output-c-string-function (symbolicate "OUTPUT-TO-C-STRING/" name
))
1598 (n-buffer (gensym "BUFFER")))
1600 (defun ,size-function
(byte)
1601 (declare (ignorable byte
))
1603 (defun ,out-function
(stream string flush-p start end
)
1604 (let ((start (or start
0))
1605 (end (or end
(length string
))))
1606 (declare (type index start end
))
1607 (synchronize-stream-output stream
)
1608 (unless (<= 0 start end
(length string
))
1609 (sequence-bounding-indices-bad string start end
))
1612 (let ((obuf (fd-stream-obuf stream
)))
1613 (setf (buffer-tail obuf
)
1614 (string-dispatch (simple-base-string
1616 (simple-array character
(*))
1619 (let ((len (buffer-length obuf
))
1620 (sap (buffer-sap obuf
))
1622 (tail (buffer-tail obuf
)))
1623 (declare (type index tail
)
1624 ;; STRING bounds have already been checked.
1625 (optimize (safety 0)))
1627 (,@(if output-restart
1628 `(catch 'output-nothing
)
1631 ((or (= start end
) (< (- len tail
) 4)))
1632 (let* ((byte (aref string start
))
1633 (bits (char-code byte
))
1634 (size ,out-size-expr
))
1638 ;; Exited from the loop normally
1640 ;; Exited via CATCH. Skip the current character
1641 ;; and try the inner loop again.
1644 (flush-output-buffer stream
)))
1646 (flush-output-buffer stream
))))
1647 (def-output-routines/variable-width
(,format
1654 (if (eql byte
#\Newline
)
1655 (setf (fd-stream-char-pos stream
) 0)
1656 (incf (fd-stream-char-pos stream
)))
1657 (let ((bits (char-code byte
))
1658 (sap (buffer-sap obuf
))
1659 (tail (buffer-tail obuf
)))
1661 (defun ,in-function
(stream buffer start requested eof-error-p
1662 &aux
(total-copied 0))
1663 (declare (type fd-stream stream
)
1664 (type index start requested total-copied
)
1666 (simple-array character
(#.
+ansi-stream-in-buffer-length
+))
1668 (let ((unread (fd-stream-unread stream
)))
1670 (setf (aref buffer start
) unread
)
1671 (setf (fd-stream-unread stream
) nil
)
1672 (setf (fd-stream-listen stream
) nil
)
1673 (incf total-copied
)))
1676 (let* ((ibuf (fd-stream-ibuf stream
))
1677 (head (buffer-head ibuf
))
1678 (tail (buffer-tail ibuf
))
1679 (sap (buffer-sap ibuf
))
1680 (decode-break-reason nil
))
1681 (declare (type index head tail
))
1682 ;; Copy data from stream buffer into user's buffer.
1683 (do ((size nil nil
))
1684 ((or (= tail head
) (= requested total-copied
)))
1685 (setf decode-break-reason
1686 (block decode-break-reason
1687 (let ((byte (sap-ref-8 sap head
)))
1688 (declare (ignorable byte
))
1689 (setq size
,in-size-expr
)
1690 (when (> size
(- tail head
))
1692 (setf (aref buffer
(+ start total-copied
)) ,in-expr
)
1696 (setf (buffer-head ibuf
) head
)
1697 (when decode-break-reason
1698 ;; If we've already read some characters on when the invalid
1699 ;; code sequence is detected, we return immediately. The
1700 ;; handling of the error is deferred until the next call
1701 ;; (where this check will be false). This allows establishing
1702 ;; high-level handlers for decode errors (for example
1703 ;; automatically resyncing in Lisp comments).
1704 (when (plusp total-copied
)
1705 (return-from ,in-function total-copied
))
1706 (when (stream-decoding-error-and-handle
1707 stream decode-break-reason
)
1709 (error 'end-of-file
:stream stream
)
1710 (return-from ,in-function total-copied
)))
1711 (setf head
(buffer-head ibuf
))
1712 (setf tail
(buffer-tail ibuf
))))
1713 (setf (buffer-head ibuf
) head
)
1714 ;; Maybe we need to refill the stream buffer.
1715 (cond ( ;; If there were enough data in the stream buffer, we're done.
1716 (= total-copied requested
)
1717 (return total-copied
))
1718 ( ;; If EOF, we're done in another way.
1719 (or (eq decode-break-reason
'eof
)
1720 (null (catch 'eof-input-catcher
1721 (refill-input-buffer stream
))))
1723 (error 'end-of-file
:stream stream
)
1724 (return total-copied
)))
1725 ;; Otherwise we refilled the stream buffer, so fall
1726 ;; through into another pass of the loop.
1728 (def-input-routine/variable-width
,in-char-function
(character
1732 (let ((byte (sap-ref-8 sap head
)))
1733 (declare (ignorable byte
))
1735 (defun ,resync-function
(stream)
1736 (let ((ibuf (fd-stream-ibuf stream
)))
1738 (input-at-least stream
2)
1739 (incf (buffer-head ibuf
))
1740 (unless (block decode-break-reason
1741 (let* ((sap (buffer-sap ibuf
))
1742 (head (buffer-head ibuf
))
1743 (byte (sap-ref-8 sap head
))
1744 (size ,in-size-expr
))
1745 (declare (ignorable byte
))
1746 (input-at-least stream size
)
1747 (setf head
(buffer-head ibuf
))
1751 (defun ,read-c-string-function
(sap element-type
)
1752 (declare (type system-area-pointer sap
))
1754 (declare (optimize (speed 3) (safety 0)))
1755 (let* ((stream ,name
)
1756 (size 0) (head 0) (byte 0) (char nil
)
1757 (decode-break-reason nil
)
1758 (length (dotimes (count (1- ARRAY-DIMENSION-LIMIT
) count
)
1759 (setf decode-break-reason
1760 (block decode-break-reason
1761 (setf byte
(sap-ref-8 sap head
)
1766 (when decode-break-reason
1767 (c-string-decoding-error ,name decode-break-reason
))
1768 (when (zerop (char-code char
))
1770 (string (make-string length
:element-type element-type
)))
1771 (declare (ignorable stream
)
1772 (type index head length
) ;; size
1773 (type (unsigned-byte 8) byte
)
1774 (type (or null character
) char
)
1775 (type string string
))
1777 (dotimes (index length string
)
1778 (setf decode-break-reason
1779 (block decode-break-reason
1780 (setf byte
(sap-ref-8 sap head
)
1785 (when decode-break-reason
1786 (c-string-decoding-error ,name decode-break-reason
))
1787 (setf (aref string index
) char
)))))
1789 (defun ,output-c-string-function
(string)
1790 (declare (type simple-string string
))
1792 (declare (optimize (speed 3) (safety 0)))
1793 (let* ((length (length string
))
1794 (char-length (make-array (1+ length
) :element-type
'index
))
1796 (+ (loop for i of-type index below length
1797 for byte of-type character
= (aref string i
)
1798 for bits
= (char-code byte
)
1799 sum
(setf (aref char-length i
)
1800 (the index
,out-size-expr
)))
1801 (let* ((byte (code-char 0))
1802 (bits (char-code byte
)))
1803 (declare (ignorable byte bits
))
1804 (setf (aref char-length length
)
1805 (the index
,out-size-expr
)))))
1807 (,n-buffer
(make-array buffer-length
1808 :element-type
'(unsigned-byte 8)))
1810 (declare (type index length buffer-length tail
)
1813 (with-pinned-objects (,n-buffer
)
1814 (let ((sap (vector-sap ,n-buffer
)))
1815 (declare (system-area-pointer sap
))
1816 (loop for i of-type index below length
1817 for byte of-type character
= (aref string i
)
1818 for bits
= (char-code byte
)
1819 for size of-type index
= (aref char-length i
)
1824 (byte (code-char bits
))
1825 (size (aref char-length length
)))
1826 (declare (ignorable bits byte size
))
1830 (setf *external-formats
*
1831 (cons '(,external-format
,in-function
,in-char-function
,out-function
1832 ,@(mapcar #'(lambda (buffering)
1833 (intern (format nil format
(string buffering
))))
1834 '(:none
:line
:full
))
1836 ,size-function
,read-c-string-function
,output-c-string-function
)
1837 *external-formats
*)))))
1839 ;;; Multiple names for the :ISO{,-}8859-* families are needed because on
1840 ;;; FreeBSD (and maybe other BSD systems), nl_langinfo("LATIN-1") will
1841 ;;; return "ISO8859-1" instead of "ISO-8859-1".
1842 (define-external-format (:latin-1
:latin1
:iso-8859-1
:iso8859-1
)
1845 (external-format-encoding-error stream bits
)
1846 (setf (sap-ref-8 sap tail
) bits
))
1849 (define-external-format (:ascii
:us-ascii
:ansi_x3.4-
1968
1850 :iso-646
:iso-646-us
:|
646|
)
1853 (external-format-encoding-error stream bits
)
1854 (setf (sap-ref-8 sap tail
) bits
))
1857 (let* ((table (let ((s (make-string 256)))
1858 (map-into s
#'code-char
1859 '(#x00
#x01
#x02
#x03
#x9c
#x09
#x86
#x7f
#x97
#x8d
#x8e
#x0b
#x0c
#x0d
#x0e
#x0f
1860 #x10
#x11
#x12
#x13
#x9d
#x85
#x08
#x87
#x18
#x19
#x92
#x8f
#x1c
#x1d
#x1e
#x1f
1861 #x80
#x81
#x82
#x83
#x84
#x0a
#x17
#x1b
#x88
#x89
#x8a
#x8b
#x8c
#x05
#x06
#x07
1862 #x90
#x91
#x16
#x93
#x94
#x95
#x96
#x04
#x98
#x99
#x9a
#x9b
#x14
#x15
#x9e
#x1a
1863 #x20
#xa0
#xe2
#xe4
#xe0
#xe1
#xe3
#xe5
#xe7
#xf1
#xa2
#x2e
#x3c
#x28
#x2b
#x7c
1864 #x26
#xe9
#xea
#xeb
#xe8
#xed
#xee
#xef
#xec
#xdf
#x21
#x24
#x2a
#x29
#x3b
#xac
1865 #x2d
#x2f
#xc2
#xc4
#xc0
#xc1
#xc3
#xc5
#xc7
#xd1
#xa6
#x2c
#x25
#x5f
#x3e
#x3f
1866 #xf8
#xc9
#xca
#xcb
#xc8
#xcd
#xce
#xcf
#xcc
#x60
#x3a
#x23
#x40
#x27
#x3d
#x22
1867 #xd8
#x61
#x62
#x63
#x64
#x65
#x66
#x67
#x68
#x69
#xab
#xbb
#xf0
#xfd
#xfe
#xb1
1868 #xb0
#x6a
#x6b
#x6c
#x6d
#x6e
#x6f
#x70
#x71
#x72
#xaa
#xba
#xe6
#xb8
#xc6
#xa4
1869 #xb5
#x7e
#x73
#x74
#x75
#x76
#x77
#x78
#x79
#x7a
#xa1
#xbf
#xd0
#xdd
#xde
#xae
1870 #x5e
#xa3
#xa5
#xb7
#xa9
#xa7
#xb6
#xbc
#xbd
#xbe
#x5b
#x5d
#xaf
#xa8
#xb4
#xd7
1871 #x7b
#x41
#x42
#x43
#x44
#x45
#x46
#x47
#x48
#x49
#xad
#xf4
#xf6
#xf2
#xf3
#xf5
1872 #x7d
#x4a
#x4b
#x4c
#x4d
#x4e
#x4f
#x50
#x51
#x52
#xb9
#xfb
#xfc
#xf9
#xfa
#xff
1873 #x5c
#xf7
#x53
#x54
#x55
#x56
#x57
#x58
#x59
#x5a
#xb2
#xd4
#xd6
#xd2
#xd3
#xd5
1874 #x30
#x31
#x32
#x33
#x34
#x35
#x36
#x37
#x38
#x39
#xb3
#xdb
#xdc
#xd9
#xda
#x9f
))
1876 (reverse-table (let ((rt (make-array 256 :element-type
'(unsigned-byte 8) :initial-element
0)))
1877 (loop for char across table for i from
0
1878 do
(aver (= 0 (aref rt
(char-code char
))))
1879 do
(setf (aref rt
(char-code char
)) i
))
1881 (define-external-format (:ebcdic-us
:ibm-037
:ibm037
)
1884 (external-format-encoding-error stream bits
)
1885 (setf (sap-ref-8 sap tail
) (aref reverse-table bits
)))
1890 (let ((latin-9-table (let ((table (make-string 256)))
1893 (setf (aref table i
) (code-char i
)))
1894 (setf (aref table
#xa4
) (code-char #x20ac
))
1895 (setf (aref table
#xa6
) (code-char #x0160
))
1896 (setf (aref table
#xa8
) (code-char #x0161
))
1897 (setf (aref table
#xb4
) (code-char #x017d
))
1898 (setf (aref table
#xb8
) (code-char #x017e
))
1899 (setf (aref table
#xbc
) (code-char #x0152
))
1900 (setf (aref table
#xbd
) (code-char #x0153
))
1901 (setf (aref table
#xbe
) (code-char #x0178
))
1903 (latin-9-reverse-1 (make-array 16
1904 :element-type
'(unsigned-byte 21)
1905 :initial-contents
'(#x0160
#x0161
#x0152
#x0153
0 0 0 0 #x0178
0 0 0 #x20ac
#x017d
#x017e
0)))
1906 (latin-9-reverse-2 (make-array 16
1907 :element-type
'(unsigned-byte 8)
1908 :initial-contents
'(#xa6
#xa8
#xbc
#xbd
0 0 0 0 #xbe
0 0 0 #xa4
#xb4
#xb8
0))))
1909 (define-external-format (:latin-9
:latin9
:iso-8859-15
:iso8859-15
)
1911 (setf (sap-ref-8 sap tail
)
1913 (if (= bits
(char-code (aref latin-9-table bits
)))
1915 (external-format-encoding-error stream byte
))
1916 (if (= (aref latin-9-reverse-1
(logand bits
15)) bits
)
1917 (aref latin-9-reverse-2
(logand bits
15))
1918 (external-format-encoding-error stream byte
))))
1919 (aref latin-9-table byte
)))
1921 (define-external-format/variable-width
(:utf-8
:utf8
) nil
1922 (let ((bits (char-code byte
)))
1923 (cond ((< bits
#x80
) 1)
1925 ((< bits
#x10000
) 3)
1928 (1 (setf (sap-ref-8 sap tail
) bits
))
1929 (2 (setf (sap-ref-8 sap tail
) (logior #xc0
(ldb (byte 5 6) bits
))
1930 (sap-ref-8 sap
(+ 1 tail
)) (logior #x80
(ldb (byte 6 0) bits
))))
1931 (3 (setf (sap-ref-8 sap tail
) (logior #xe0
(ldb (byte 4 12) bits
))
1932 (sap-ref-8 sap
(+ 1 tail
)) (logior #x80
(ldb (byte 6 6) bits
))
1933 (sap-ref-8 sap
(+ 2 tail
)) (logior #x80
(ldb (byte 6 0) bits
))))
1934 (4 (setf (sap-ref-8 sap tail
) (logior #xf0
(ldb (byte 3 18) bits
))
1935 (sap-ref-8 sap
(+ 1 tail
)) (logior #x80
(ldb (byte 6 12) bits
))
1936 (sap-ref-8 sap
(+ 2 tail
)) (logior #x80
(ldb (byte 6 6) bits
))
1937 (sap-ref-8 sap
(+ 3 tail
)) (logior #x80
(ldb (byte 6 0) bits
)))))
1938 (cond ((< byte
#x80
) 1)
1939 ((< byte
#xc2
) (return-from decode-break-reason
1))
1943 (code-char (ecase size
1945 (2 (let ((byte2 (sap-ref-8 sap
(1+ head
))))
1946 (unless (<= #x80 byte2
#xbf
)
1947 (return-from decode-break-reason
2))
1948 (dpb byte
(byte 5 6) byte2
)))
1949 (3 (let ((byte2 (sap-ref-8 sap
(1+ head
)))
1950 (byte3 (sap-ref-8 sap
(+ 2 head
))))
1951 (unless (and (<= #x80 byte2
#xbf
)
1952 (<= #x80 byte3
#xbf
))
1953 (return-from decode-break-reason
3))
1954 (dpb byte
(byte 4 12) (dpb byte2
(byte 6 6) byte3
))))
1955 (4 (let ((byte2 (sap-ref-8 sap
(1+ head
)))
1956 (byte3 (sap-ref-8 sap
(+ 2 head
)))
1957 (byte4 (sap-ref-8 sap
(+ 3 head
))))
1958 (unless (and (<= #x80 byte2
#xbf
)
1959 (<= #x80 byte3
#xbf
)
1960 (<= #x80 byte4
#xbf
))
1961 (return-from decode-break-reason
4))
1962 (dpb byte
(byte 3 18)
1963 (dpb byte2
(byte 6 12)
1964 (dpb byte3
(byte 6 6) byte4
))))))))
1966 ;;;; utility functions (misc routines, etc)
1968 ;;; Fill in the various routine slots for the given type. INPUT-P and
1969 ;;; OUTPUT-P indicate what slots to fill. The buffering slot must be
1970 ;;; set prior to calling this routine.
1971 (defun set-fd-stream-routines (fd-stream element-type external-format
1972 input-p output-p buffer-p
)
1973 (let* ((target-type (case element-type
1974 (unsigned-byte '(unsigned-byte 8))
1975 (signed-byte '(signed-byte 8))
1976 (:default
'character
)
1978 (character-stream-p (subtypep target-type
'character
))
1979 (bivalent-stream-p (eq element-type
:default
))
1980 normalized-external-format
1981 (bin-routine #'ill-bin
)
1984 (cin-routine #'ill-in
)
1987 (input-type nil
) ;calculated from bin-type/cin-type
1988 (input-size nil
) ;calculated from bin-size/cin-size
1989 (read-n-characters #'ill-in
)
1990 (bout-routine #'ill-bout
)
1993 (cout-routine #'ill-out
)
1998 (output-bytes #'ill-bout
))
2000 ;; Ensure that we have buffers in the desired direction(s) only,
2001 ;; getting new ones and dropping/resetting old ones as necessary.
2002 (let ((obuf (fd-stream-obuf fd-stream
)))
2006 (setf (fd-stream-obuf fd-stream
) (get-buffer)))
2008 (setf (fd-stream-obuf fd-stream
) nil
)
2009 (release-buffer obuf
))))
2011 (let ((ibuf (fd-stream-ibuf fd-stream
)))
2015 (setf (fd-stream-ibuf fd-stream
) (get-buffer)))
2017 (setf (fd-stream-ibuf fd-stream
) nil
)
2018 (release-buffer ibuf
))))
2020 ;; FIXME: Why only for output? Why unconditionally?
2022 (setf (fd-stream-char-pos fd-stream
) 0))
2024 (when (and character-stream-p
2025 (eq external-format
:default
))
2026 (/show0
"/getting default external format")
2027 (setf external-format
(default-external-format)))
2030 (when (or (not character-stream-p
) bivalent-stream-p
)
2031 (multiple-value-setq (bin-routine bin-type bin-size read-n-characters
2032 normalized-external-format
)
2033 (pick-input-routine (if bivalent-stream-p
'(unsigned-byte 8)
2037 (error "could not find any input routine for ~S" target-type
)))
2038 (when character-stream-p
2039 (multiple-value-setq (cin-routine cin-type cin-size read-n-characters
2040 normalized-external-format
)
2041 (pick-input-routine target-type external-format
))
2043 (error "could not find any input routine for ~S" target-type
)))
2044 (setf (fd-stream-in fd-stream
) cin-routine
2045 (fd-stream-bin fd-stream
) bin-routine
)
2046 ;; character type gets preferential treatment
2047 (setf input-size
(or cin-size bin-size
))
2048 (setf input-type
(or cin-type bin-type
))
2049 (when normalized-external-format
2050 (setf (fd-stream-external-format fd-stream
)
2051 normalized-external-format
))
2052 (when (= (or cin-size
1) (or bin-size
1) 1)
2053 (setf (fd-stream-n-bin fd-stream
) ;XXX
2054 (if (and character-stream-p
(not bivalent-stream-p
))
2056 #'fd-stream-read-n-bytes
))
2057 ;; Sometimes turn on fast-read-char/fast-read-byte. Switch on
2058 ;; for character and (unsigned-byte 8) streams. In these
2059 ;; cases, fast-read-* will read from the
2060 ;; ansi-stream-(c)in-buffer, saving function calls.
2061 ;; Otherwise, the various data-reading functions in the stream
2062 ;; structure will be called.
2064 (not bivalent-stream-p
)
2065 ;; temporary disable on :io streams
2067 (cond (character-stream-p
2068 (setf (ansi-stream-cin-buffer fd-stream
)
2069 (make-array +ansi-stream-in-buffer-length
+
2070 :element-type
'character
)))
2071 ((equal target-type
'(unsigned-byte 8))
2072 (setf (ansi-stream-in-buffer fd-stream
)
2073 (make-array +ansi-stream-in-buffer-length
+
2074 :element-type
'(unsigned-byte 8))))))))
2077 (when (or (not character-stream-p
) bivalent-stream-p
)
2078 (multiple-value-setq (bout-routine bout-type bout-size output-bytes
2079 normalized-external-format
)
2080 (pick-output-routine (if bivalent-stream-p
2083 (fd-stream-buffering fd-stream
)
2085 (unless bout-routine
2086 (error "could not find any output routine for ~S buffered ~S"
2087 (fd-stream-buffering fd-stream
)
2089 (when character-stream-p
2090 (multiple-value-setq (cout-routine cout-type cout-size output-bytes
2091 normalized-external-format
)
2092 (pick-output-routine target-type
2093 (fd-stream-buffering fd-stream
)
2095 (unless cout-routine
2096 (error "could not find any output routine for ~S buffered ~S"
2097 (fd-stream-buffering fd-stream
)
2099 (when normalized-external-format
2100 (setf (fd-stream-external-format fd-stream
)
2101 normalized-external-format
))
2102 (when character-stream-p
2103 (setf (fd-stream-output-bytes fd-stream
) output-bytes
))
2104 (setf (fd-stream-out fd-stream
) cout-routine
2105 (fd-stream-bout fd-stream
) bout-routine
2106 (fd-stream-sout fd-stream
) (if (eql cout-size
1)
2107 #'fd-sout
#'ill-out
))
2108 (setf output-size
(or cout-size bout-size
))
2109 (setf output-type
(or cout-type bout-type
)))
2111 (when (and input-size output-size
2112 (not (eq input-size output-size
)))
2113 (error "Element sizes for input (~S:~S) and output (~S:~S) differ?"
2114 input-type input-size
2115 output-type output-size
))
2116 (setf (fd-stream-element-size fd-stream
)
2117 (or input-size output-size
))
2119 (setf (fd-stream-element-type fd-stream
)
2120 (cond ((equal input-type output-type
)
2126 ((subtypep input-type output-type
)
2128 ((subtypep output-type input-type
)
2131 (error "Input type (~S) and output type (~S) are unrelated?"
2135 ;; Unix's close(2) can fail in various ways. FIXME: look around for
2136 ;; other calls to UNIX-CLOSE, and maybe replace them with this.
2137 (defun close-descriptor (descriptor &optional signaler
)
2138 "Try to close(2) DESCRIPTOR. Retry in case close(2) fails and
2139 sets errno to EINTR. If close(2) fails and sets errno to any
2140 value other than EINTR, then use SIGNALER as follows: if SIGNALER
2141 is a function, call it with the descriptor and errno; if SIGNALER
2142 is T, signal an error of type ERROR; if SIGNALER is NIL, silently
2143 ignore the close(2) error. (In this case, we can silently leak a
2144 descriptor; don't use this unless you have to.)"
2145 (loop (multiple-value-bind (status errno
)
2146 (os-close descriptor
)
2149 (when (/= errno sb
!unix
:eintr
)
2150 (cond ((functionp signaler
)
2151 (funcall signaler descriptor errno
))
2153 (error "failed to close() fd ~D: (~A)"
2154 descriptor
(strerror errno
)))))))))
2156 ;;; Handles the resource-release aspects of stream closing, and marks
2158 (defun release-fd-stream-resources (fd-stream)
2160 ;; Disable interrupts so that a asynch unwind will not leave us
2161 ;; with a dangling finalizer (that would close the same
2162 ;; --possibly reassigned-- FD again), or a stream with a closed
2163 ;; FD that appears open.
2165 ;; Drop handlers first.
2166 (when (fd-stream-handler fd-stream
)
2167 (remove-fd-handler (fd-stream-handler fd-stream
))
2168 (setf (fd-stream-handler fd-stream
) nil
))
2169 (close-descriptor (fd-stream-fd fd-stream
)
2171 (declare (ignore fd
))
2172 (simple-stream-perror
2173 "failed to close() the descriptor in ~A"
2175 (set-closed-flame fd-stream
)
2176 (when (fboundp 'cancel-finalization
)
2177 (cancel-finalization fd-stream
)))
2178 ;; On error unwind from WITHOUT-INTERRUPTS.
2179 (serious-condition (e)
2181 ;; Release all buffers. If this is undone, or interrupted,
2182 ;; we're still safe: buffers have finalizers of their own.
2183 (release-fd-stream-buffers fd-stream
))
2185 ;;; Flushes the current input buffer and unread chatacter, and returns
2186 ;;; the input buffer, and the amount of of flushed input in bytes.
2187 (defun flush-input-buffer (stream)
2188 (let ((unread (if (fd-stream-unread stream
)
2191 (setf (fd-stream-unread stream
) nil
)
2192 (let ((ibuf (fd-stream-ibuf stream
)))
2194 (let ((head (buffer-head ibuf
))
2195 (tail (buffer-tail ibuf
)))
2196 (values (reset-buffer ibuf
) (- (+ unread tail
) head
)))
2197 (values nil unread
)))))
2199 (defun fd-stream-clear-input (stream)
2200 (flush-input-buffer stream
)
2201 #!+(and win32 win32-uses-file-handles
)
2203 (sb!win32
:handle-clear-input
(fd-stream-fd stream
))
2204 (setf (fd-stream-listen stream
) nil
))
2205 #!+(and win32
(not win32-uses-file-handles
))
2208 (sb!win32
:fd-clear-input
(fd-stream-fd stream
))
2209 (setf (fd-stream-listen stream
) nil
))
2211 (catch 'eof-input-catcher
2212 (loop until
(sysread-may-block-p stream
)
2214 (refill-input-buffer stream
)
2215 (reset-buffer (fd-stream-ibuf stream
)))
2218 ;;; Handle miscellaneous operations on FD-STREAM.
2219 (defun fd-stream-misc-routine (fd-stream operation
&optional arg1 arg2
)
2220 (declare (ignore arg2
))
2223 (labels ((do-listen ()
2224 (let ((ibuf (fd-stream-ibuf fd-stream
)))
2225 (or (not (eql (buffer-head ibuf
) (buffer-tail ibuf
)))
2226 (fd-stream-listen fd-stream
)
2228 (sb!win32
:fd-listen
(fd-stream-fd fd-stream
))
2230 ;; If the read can block, LISTEN will certainly return NIL.
2231 (if (sysread-may-block-p fd-stream
)
2233 ;; Otherwise select(2) and CL:LISTEN have slightly
2234 ;; different semantics. The former returns that an FD
2235 ;; is readable when a read operation wouldn't block.
2236 ;; That includes EOF. However, LISTEN must return NIL
2238 (progn (catch 'eof-input-catcher
2239 ;; r-b/f too calls select, but it shouldn't
2240 ;; block as long as read can return once w/o
2242 (refill-input-buffer fd-stream
))
2243 ;; At this point either IBUF-HEAD != IBUF-TAIL
2244 ;; and FD-STREAM-LISTEN is NIL, in which case
2245 ;; we should return T, or IBUF-HEAD ==
2246 ;; IBUF-TAIL and FD-STREAM-LISTEN is :EOF, in
2247 ;; which case we should return :EOF for this
2248 ;; call and all future LISTEN call on this stream.
2249 ;; Call ourselves again to determine which case
2254 (setf (fd-stream-unread fd-stream
) arg1
)
2255 (setf (fd-stream-listen fd-stream
) t
))
2257 (when (open-stream-p fd-stream
)
2258 (finish-fd-stream-output fd-stream
)
2259 (release-fd-stream-resources fd-stream
)
2260 (do-after-close-actions fd-stream arg1
)))
2262 (fd-stream-clear-input fd-stream
))
2264 (flush-output-buffer fd-stream
))
2266 (finish-fd-stream-output fd-stream
))
2268 (fd-stream-element-type fd-stream
))
2270 (fd-stream-external-format fd-stream
))
2272 (= 1 (the (member 0 1)
2273 (sb!unix
:unix-isatty
(fd-stream-fd fd-stream
)))))
2277 (fd-stream-char-pos fd-stream
))
2279 (unless (stream-pathname fd-stream
)
2280 ;; This is a TYPE-ERROR because ANSI's species FILE-LENGTH
2281 ;; "should signal an error of type TYPE-ERROR if stream is not
2282 ;; a stream associated with a file". Too bad there's no very
2283 ;; appropriate value for the EXPECTED-TYPE slot..
2284 (error 'simple-type-error
2286 :expected-type
'file-stream
2287 :format-control
"~S is not a stream associated with a file."
2288 :format-arguments
(list fd-stream
)))
2289 ;; OS-FILE-LENGTH wraps fstat() and GetFileSize(), both of which
2290 ;; can return NIL and an errno. Since ANSI says we're to return
2291 ;; NIL if the length cannot be determined, we just return the
2292 ;; first value. (Before 1.0.15 or so, we errored when fstat()
2294 (truncate (os-file-length (fd-stream-fd fd-stream
))
2295 (fd-stream-element-size fd-stream
)))
2296 (:file-string-length
2298 (character (fd-stream-character-size fd-stream arg1
))
2299 (string (fd-stream-string-size fd-stream arg1
))))
2302 (fd-stream-set-file-position fd-stream arg1
)
2303 (fd-stream-get-file-position fd-stream
)))))
2305 ;; FIXME: Think about this.
2307 ;; (defun finish-fd-stream-output (fd-stream)
2308 ;; (let ((timeout (fd-stream-timeout fd-stream)))
2309 ;; (loop while (fd-stream-output-queue fd-stream)
2310 ;; ;; FIXME: SIGINT while waiting for a timeout will
2311 ;; ;; cause a timeout here.
2312 ;; do (when (and (not (serve-event timeout)) timeout)
2313 ;; (signal-timeout 'io-timeout
2314 ;; :stream fd-stream
2315 ;; :direction :write
2316 ;; :seconds timeout)))))
2318 (defun finish-fd-stream-output (stream)
2319 (flush-output-buffer stream
)
2321 ((null (fd-stream-output-queue stream
)))
2322 (serve-all-events)))
2324 (defun fd-stream-get-file-position (stream)
2325 (declare (fd-stream stream
))
2327 (let ((posn (os-seek (fd-stream-fd stream
) 0 t
)))
2328 (declare (type (or (alien sb
!unix
:off-t
) null
) posn
))
2329 ;; We used to return NIL for errno==ESPIPE, and signal an error
2330 ;; in other failure cases. However, CLHS says to return NIL if
2331 ;; the position cannot be determined -- so that's what we do.
2332 (when (integerp posn
)
2333 ;; Adjust for buffered output: If there is any output
2334 ;; buffered, the *real* file position will be larger
2335 ;; than reported by lseek() because lseek() obviously
2336 ;; cannot take into account output we have not sent
2338 (dolist (buffer (fd-stream-output-queue stream
))
2339 (incf posn
(- (buffer-tail buffer
) (buffer-head buffer
))))
2340 (let ((obuf (fd-stream-obuf stream
)))
2342 (incf posn
(buffer-tail obuf
))))
2343 ;; Adjust for unread input: If there is any input
2344 ;; read from UNIX but not supplied to the user of the
2345 ;; stream, the *real* file position will smaller than
2346 ;; reported, because we want to look like the unread
2347 ;; stuff is still available.
2348 (let ((ibuf (fd-stream-ibuf stream
)))
2350 (decf posn
(- (buffer-tail ibuf
) (buffer-head ibuf
)))))
2351 (when (fd-stream-unread stream
)
2353 ;; Divide bytes by element size.
2354 (truncate posn
(fd-stream-element-size stream
))))))
2356 (defun fd-stream-set-file-position (stream position-spec
)
2357 (declare (fd-stream stream
))
2358 (check-type position-spec
2359 (or (alien sb
!unix
:off-t
) (member nil
:start
:end
))
2360 "valid file position designator")
2363 ;; Make sure we don't have any output pending, because if we
2364 ;; move the file pointer before writing this stuff, it will be
2365 ;; written in the wrong location.
2366 (finish-fd-stream-output stream
)
2367 ;; Disable interrupts so that interrupt handlers doing output
2370 (unless (fd-stream-output-finished-p stream
)
2371 ;; We got interrupted and more output came our way during
2372 ;; the interrupt. Wrapping the FINISH-FD-STREAM-OUTPUT in
2373 ;; WITHOUT-INTERRUPTS gets nasty as it can signal errors,
2374 ;; so we prefer to do things like this...
2376 ;; Clear out any pending input to force the next read to go to
2378 (flush-input-buffer stream
)
2379 ;; Trash cached value for listen, so that we check next time.
2380 (setf (fd-stream-listen stream
) nil
)
2382 (multiple-value-bind (offset origin
)
2389 (values (* position-spec
(fd-stream-element-size stream
))
2391 (declare (type (alien sb
!unix
:off-t
) offset
))
2392 (let ((posn (os-seek (fd-stream-fd stream
) offset origin
)))
2393 ;; CLHS says to return true if the file-position was set
2394 ;; succesfully, and NIL otherwise. We are to signal an error
2395 ;; only if the given position was out of bounds, and that is
2396 ;; dealt with above. In times past we used to return NIL for
2397 ;; errno==ESPIPE, and signal an error in other cases.
2399 ;; FIXME: We are still liable to signal an error if flushing
2401 (return-from fd-stream-set-file-position
2402 (typep posn
'(alien sb
!unix
:off-t
))))))))
2407 ;;; Create a stream for the given Unix file descriptor.
2409 ;;; If INPUT is non-NIL, allow input operations. If OUTPUT is non-nil,
2410 ;;; allow output operations. If neither INPUT nor OUTPUT is specified,
2411 ;;; default to allowing input.
2413 ;;; ELEMENT-TYPE indicates the element type to use (as for OPEN).
2415 ;;; BUFFERING indicates the kind of buffering to use.
2417 ;;; TIMEOUT (if true) is the number of seconds to wait for input. If
2418 ;;; NIL (the default), then wait forever. When we time out, we signal
2420 (defun make-fd-stream (fd
2423 (output nil output-p
)
2424 (element-type 'base-char
)
2426 (external-format :default
)
2438 (format nil
"file ~A" file
)
2439 (format nil
"descriptor ~W" fd
))))
2440 (declare (type index fd
) (type (or real null
) timeout
)
2441 (type (member :none
:line
:full
) buffering
))
2442 (cond ((not (or input-p output-p
))
2444 ((not (or input output
))
2445 (error "File descriptor must be opened either for input or output.")))
2446 (let ((stream (%make-fd-stream
:fd fd
2447 :buffering buffering
2448 :dual-channel-p dual-channel-p
2449 :external-format external-format
2452 (coerce timeout
'single-float
)
2457 :after-close after-close
2460 (set-fd-stream-routines stream element-type external-format
2461 input output input-buffer-p
)
2462 (when (and auto-close
(fboundp 'finalize
))
2465 ;; FIXME: CLOSE-DESCRIPTOR takes care of EINTR, but
2466 ;; should we signal an error for other close()
2467 ;; failures here? I don't know what consequences
2468 ;; follow from signalling error during GC. But if
2469 ;; close() fails, we really shouldn't lose track of
2471 (close-descriptor fd
)
2473 (format *terminal-io
* "** closed file descriptor ~W **~%"
2478 ;;; Since SUSv3 mkstemp() doesn't specify the mode of the created file
2479 ;;; and since we have to implement most of this ourselves for Windows
2480 ;;; anyway, it seems worthwhile to depart from the mkstemp()
2481 ;;; specification by taking a mode to use when creating the new file.
2482 ;;; This was introduced around 1.0.13, was a thin wrapper around a
2483 ;;; routine in the runtime, and was used in only a very restricted
2484 ;;; way; before 1.0.15, I noticed that there were some drawbacks in
2485 ;;; the C library routines in that routine in the runtime that limited
2486 ;;; the general-purposeness of that routine, and so rewrote it all in
2487 ;;; Lisp; doing it in Lisp also means that the user can control the
2488 ;;; randomness manually, if necessary.
2489 (defvar *random-filename-random-state
* nil
2490 "Random-state used when creating random filenames. SETF-able,
2491 if you want to produce a predictable sequence of filenames. If
2492 NIL, generating the next random filename will assign this
2493 variable a new, randomly generated random-state.")
2495 (defun random-filename (template-string)
2496 (unless *random-filename-random-state
*
2497 (setf *random-filename-random-state
* (make-random-state t
)))
2498 (let* (;; mkstemp() uses POSIX's so-called "portable filename
2499 ;; character set" for filling the template. We exclude #\.,
2500 ;; since that's our pathname type separator.
2501 (random-charset #.
(format nil
"~@{~A~}"
2502 "abcdefghijklmnopqrstuvwxyz"
2503 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2505 (X-pos (1+ (position #\X template-string
:test
'char
/= :from-end t
)))
2506 (template-length (- (length template-string
) X-pos
))
2507 (template-stem (subseq template-string
0 X-pos
)))
2508 (unless (>= template-length
6)
2509 (error "bad mkstemp template ~A" template-string
))
2510 (let ((random-suffix (loop
2511 repeat template-length
2515 64 *random-filename-random-state
*)))))
2516 (concatenate 'string template-stem random-suffix
))))
2520 ;; Circa 1.0.14, the innards of OPEN have been entirely rewritten from
2521 ;; the CMU code, with a few goals in mind: (1) to be usable as a
2522 ;; substrate for more than one streams API, to prevent functionality
2523 ;; skew; (2) to be asynch-interrupt-safe and slightly less prone to
2524 ;; breakage due to fork(), (3) to try to do as much as possible using
2525 ;; Lisp-level file system functions, rather than raw Unix system
2526 ;; calls, so that we have some stress-testing on that code, so that we
2527 ;; get consistent, Lisp-level error detection and reporting when
2528 ;; things go awry, and since some of the system calls' behaviors vary
2529 ;; a bit across Unix and Windows.
2531 ;; When we construct a stream, we store a function to be called during
2532 ;; CLOSE, and also a PID. This routine runs the close-time code,
2533 ;; after the descriptor is closed, in case this process is responsible
2535 (defun do-after-close-actions (stream abortp
)
2536 (when (and #!+unix
(eql (sb!unix
:unix-getpid
) (stream-owner-pid stream
))
2537 (stream-after-close stream
))
2538 (with-simple-restart (continue "Continue, leaving files in place.")
2539 (funcall (stream-after-close stream
) stream abortp
))
2540 (setf (stream-after-close stream
) nil
)))
2542 ;; We have separate functions for actions to be performed after
2543 ;; constructing the stream, but before returning it to the user. The
2544 ;; only one that's common to all ways of building SBCL is the one that
2545 ;; repositions the file pointer after constructing the stream.
2546 (defun open-if-exists-append (stream)
2547 (file-position stream
:end
))
2549 (defvar *open-backup-suffix
* ".bak"
2550 "Backup suffix used when opening with :RENAME.")
2552 (defun open-backup-pathname (pathname)
2553 "Return the name that a file whose truename is PATHNAME will have
2554 after a successful :RENAME opening. Note that this is a syntactic
2555 operation, and does not examine the file system; if PATHNAME names a
2556 symlink, calling OPEN on PATHNAME with IF-EXISTS :RENAME will rename a
2557 file whose truename is not PATHNAME."
2558 (parse-native-namestring
2559 (concatenate 'string
(native-namestring pathname
) *open-backup-suffix
*)
2560 (pathname-host pathname
)))
2562 (defun close-abort-delete (stream abortp
)
2563 "During an aborting close, delete the file associated with the
2566 (delete-file (stream-truename stream
))))
2568 (defun make-deleted-file-closer (stream)
2569 (let ((old-after-close (stream-after-close stream
)))
2570 (lambda (stream abort
)
2571 (declare (ignore abort
))
2572 (if (member old-after-close
2573 #!+open-lazy-file-disposition
2574 '(#'close-lazy-supersede
#'close-lazy-rename
)
2575 #!-open-lazy-file-disposition
2576 '(#'close-delete-altname
#'close-rename-altname
))
2577 (funcall old-after-close stream t
)
2578 (delete-file (stream-truename stream
))))))
2580 ;; NTFS supports hard links, and some Unixes can mount file systems
2581 ;; that don't (e.g., FAT). So try linking first on both Unix and
2582 ;; Windows, and then fail over to renaming.
2583 (defun make-temporary-name-for-file (pathname)
2584 "Link or rename PATHNAME to a random name in the same
2585 directory. If file does not exist, returns NIL. Otherwise,
2586 returns the random name and a boolean that's true in case the
2587 file was renamed, rather than linked."
2588 (loop with filename
= (native-namestring pathname
)
2589 for temppath
= (parse-native-namestring
2591 (concatenate 'string filename
"-XXXXXX"))
2592 (pathname-host pathname
))
2593 thereis
(handler-case (link-file pathname temppath
)
2594 (file-does-not-exist () (return nil
))
2595 (file-exists () nil
)
2598 (replace-file pathname temppath
)))
2599 (values new-name t
))))))
2601 ;; FIXME: rewrite this, to make it clearer that this is
2602 ;; transaction-like?
2603 (defmacro with-temporary-name-for-file
((var pathname
) &body body
)
2604 "Run BODY with VAR bound to a new, randomly selected name for
2605 the file named by PATHNAME. If control leaves body abnormally,
2606 try to restore FILE to its old name. Otherwise, the file named
2607 by PATHNAME at the start of BODY will be named by the value of
2608 VAR after the body."
2609 (with-unique-names (oldname renamedp
)
2610 `(let ((,oldname
,pathname
))
2611 (multiple-value-bind (,var
,renamedp
)
2612 (make-temporary-name-for-file ,oldname
)
2614 (multiple-value-prog1 (progn ,@body
) (setf ,var nil
))
2617 (rename-file ,var
,oldname
)
2618 (delete-file ,var
))))))))
2620 ;; The actions to conduct at OPEN- and CLOSE-time differ slightly in
2621 ;; the lazy/non-lazy file disposition worlds. In fact, the same basic
2622 ;; things happen, just at different times.
2623 #!-open-lazy-file-disposition
2625 (defun open-eager-rename (stream)
2626 "For openings that create a file with mkstemp(), rename the new
2627 file to have its final name before returning a stream to the
2628 user, and modify the stream so that a previously existing file
2629 gets renamed or deleted at CLOSE-time."
2630 (with-temporary-name-for-file (temp-name (stream-altname stream
))
2631 (rename-file (stream-truename stream
)
2632 (merge-pathnames (stream-altname stream
)
2633 (make-pathname :type
:unspecific
)))
2634 (setf (stream-truename stream
) (stream-altname stream
)
2635 (stream-altname stream
) temp-name
)))
2637 (defun close-rename-altname (stream abortp
)
2638 "When closing a stream opened with IF-EXISTS :RENAME either
2639 restore or rename the file that existed before the stream was
2642 ;; FIXME: Win32's MoveFileEx can atomically rename files. I
2643 ;; don't know whether that's how RENAME-FILE should be
2644 ;; implemented, but we can use it here, in any case.
2645 #+win32
(delete-file (stream-truename stream
))
2646 (rename-file (stream-altname stream
) (stream-truename stream
))
2647 (return-from close-rename-altname
))
2648 (rename-file (stream-altname stream
)
2649 (merge-pathnames (open-backup-pathname
2650 (stream-truename stream
))
2651 (make-pathname :type
:unspecific
))))
2653 (defun close-delete-altname (stream abortp
)
2654 "When closing a stream opened with IF-EXISTS :RENAME-AND-DELETE,
2655 either restore or delete the file that existed before the stream
2656 was opened. If SBCL was built with the
2657 feature :OPEN-SUPERSEDE-IS-RENAME-AND-DELETE, this gets called
2658 during a CLOSE of a stream opened with :SUPERSEDE, too."
2660 ;; FIXME: Win32's MoveFileEx can atomically rename files. I
2661 ;; don't know whether that's how RENAME-FILE should be
2662 ;; implemented, but we can use it here, in any case.
2663 #+win32
(delete-file (stream-truename stream
))
2664 (rename-file (stream-altname stream
) (stream-truename stream
))
2665 (return-from close-delete-altname
))
2666 (delete-file (stream-altname stream
)))
2668 (defun close-delete-pathname (stream abortp
)
2669 "During an aborting close, delete the file named by the name
2670 used to open the stream. (This behavior makes no sense, but
2671 it's what CMU/SBCL has always done for :SUPERSEDE.)"
2673 (delete-file (pathname stream
)))))
2675 ;; Note that in the :OPEN-LAZY-FILE-DISPOSITION world, an opening that
2676 ;; creates a new file doesn't touch any existing file until CLOSE-time.
2677 #!+open-lazy-file-disposition
2679 (defun close-lazy-supersede (stream abortp
)
2680 "When closing a stream opened with IF-EXISTS :RENAME-AND-DELETE,
2681 either rename the file associated with the stream into place, or
2682 delete the file associated with the stream. If SBCL was built
2683 with the feature :OPEN-SUPERSEDE-IS-RENAME-AND-DELETE, this gets
2684 called during a CLOSE of a stream opened with :SUPERSEDE, too."
2686 (delete-file (stream-truename stream
))
2687 (return-from close-lazy-supersede
))
2688 (rename-file (stream-truename stream
) (stream-altname stream
))
2689 (setf (stream-truename stream
) (stream-altname stream
)))
2691 (defun close-lazy-rename (stream abortp
)
2692 "When closing a stream opened with IF-EXISTS :RENAME-AND-DELETE,
2693 either rename the file associated with the stream into place and
2694 rename the old file to the backup name, or delete the file
2695 associated with the stream."
2697 (delete-file (stream-truename stream
))
2698 (return-from close-lazy-rename
))
2699 (let ((backup-path (merge-pathnames (open-backup-pathname
2700 (stream-altname stream
))
2701 (make-pathname :type
:unspecific
)))
2703 (with-temporary-name-for-file (temp-name (stream-altname stream
))
2704 (rename-file (stream-truename stream
) (stream-altname stream
))
2705 (setf link-path temp-name
;hold onto TEMP-NAME for use below.
2706 (stream-truename stream
) (stream-altname stream
)))
2707 ;; We do this final rename outside of
2708 ;; WITH-TEMPORARY-NAME-FOR-FILE so that if it fails, no data
2709 ;; will have been lost (though the old file will be left with a
2710 ;; random name if the user aborts).
2712 (rename-file link-path backup-path
)))))
2714 (defun open-element-type-satisfies-function (type)
2715 (or (member type
'(:default unsigned-byte signed-byte
))
2716 (subtypep type
'character
)
2717 ;; XXX: this should be a /finite/ subtype of integer, but I
2718 ;; don't know if we are able to say that.
2719 (subtypep type
'integer
)))
2721 ;; I think this macro captures the common aspect of calling a
2722 ;; VALUES-FORM that returns values that include something that must
2723 ;; not be allowed to leak. FIXME: some other places could perhaps
2724 ;; take advantage of this (e.g., the temporary file descriptor used in
2726 (defmacro uninterruptibly-bind-and-protect
2727 ((&rest vars
) values-form form
&body cleanup-forms
)
2728 "Bind VARS to the return values of VALUES-FORM, evaluate FORM
2729 and then CLEANUP-FORMS with VARS so bound; CLEANUP-FORMS will be
2730 run even if control transfers out of FORM abnormally.
2731 Asynchronous interrupts are enabled during FORM, and nowhere
2733 `(without-interrupts
2734 (multiple-value-bind ,vars
,values-form
2736 (with-local-interrupts ,form
)
2739 ;; The following function, OPEN-FILE, is a high-level internal
2740 ;; primitive that's meant to do all the work of OPEN except for
2741 ;; constructing a stream. It's designed to suit the needs of
2742 ;; FD-STREAMS and SB-SIMPLE-STREAMS, but should also suffice for other
2743 ;; ways of implementing ANSI FILE-STREAMs.
2745 ;; Note: as far as I can tell, any call to a function that returns a
2746 ;; file descriptor while interrupts are enabled exposes a window
2747 ;; during which an asynchronous interrupt can lead to fd leak. So
2748 ;; while OPEN-FILE must disable interrupts around open() calls, we
2749 ;; don't want to its callers to have to disable interrupts around
2750 ;; OPEN-FILE, since OPEN-FILE must do various other error-prone things
2751 ;; (e.g., resolving truenames). So in order to allow our callers to
2752 ;; be ignorant of asynchronous interrupt concerns, we don't have
2753 ;; OPEN-FILE return a descriptor, but instead have it assign a special
2754 ;; variable as described in the docstring.
2756 (filespec direction if-does-not-exist if-exists element-type
2758 "Open a file according to OPEN-like arguments. FILESPEC is the
2759 verbatim (unmerged, untranslated) argument to OPEN. DIRECTION
2760 and ELEMENT-TYPE are the arguments supplied to or defaulted in
2761 OPEN. IF-DOES-NOT-EXIST and IF-EXISTS are the arguments
2762 supplied to OPEN, or the symbol SB-IMPL::DEFAULT if the
2763 argument was not supplied. OS-OPEN-ARGS is an
2764 OS-OPEN-ARGUMENTS list, containing any extra arguments to be
2765 passed down to the system's open syscall.
2767 Callers must bind *FILE-DESCRIPTOR* in the dynamic
2768 environment. If OPEN-FILE succeeds, it sets *FILE-DESCRIPTOR*
2769 to an integer, and returns seven values to be used in the
2772 1. the result of merging FILESPEC,
2774 2. the name of the file actually open,
2776 3. a pathname or NIL, used as bookkeeping for some kinds of
2779 4. a boolean that's true if the stream is for input,
2781 5. a boolean that's true if the stream is for output,
2783 6. a function of one argument to call on the to-be-created
2784 stream before returning it to the user,
2786 7. a function of two arguments to be called after closing the
2787 descriptor during CLOSE; the first argument to this
2788 function is the stream, the second a generalized boolean
2789 that's true in case the stream is being closed in an
2792 The caller is responsible for constructing a stream, calling
2793 the first function, and arranging for the second function to
2794 be called during CLOSE.
2796 If OPEN-FILE does not open a file, either because IF-EXISTS
2797 and IF-DOES-NOT-EXIST inhibit opening or because of file
2798 system errors during open(), OPEN-FILE will return NIL or
2799 signal a FILE-ERROR, as determined by the arguments and file
2802 If OPEN-FILE signals an error or returns NIL,
2803 *FILE-DESCRIPTOR* will have the value NIL after control
2804 returns from OPEN-FILE.
2806 If any error occurs after a file has been opened, OPEN-FILE
2807 will close the descriptor.
2809 Note that OPEN-FILE can signal FILE-ERRORs not directly
2810 related to a call to open(): truename resolution, pathname
2811 unparsing, logical pathname translation, etc. can all error."
2812 (declare (type (member :input
:output
:io
:probe
) direction
))
2813 (declare (type (satisfies open-element-type-satisfies-function
)
2815 (declare (ignore element-type
))
2817 ;; This is our internal protocol.
2818 (unless (boundp '*file-descriptor
*)
2819 (bug "*FILE-DESCRIPTOR* is not bound at start of OPEN-FILE."))
2821 ;; Basic sanity stuff first. Should be straightforward
2822 ;; transcriptions of things from the CLHS.
2823 (setf filespec
(pathname filespec
))
2824 (when (wild-pathname-p filespec
)
2825 (error 'simple-file-error
2827 :format-control
"can't open a wild pathname: ~A"
2828 :format-arguments
(list filespec
)))
2829 (when (eq if-exists
'default
)
2830 (if (member direction
'(:output
:io
))
2831 (setf if-exists
(if (eq (pathname-version filespec
) :newest
)
2834 (setf if-exists nil
)))
2835 (when (eq if-does-not-exist
'default
)
2836 (setf if-does-not-exist
2838 ((eq direction
:probe
)
2840 ((or (eq direction
:input
)
2841 (member if-exists
'(:overwrite
:append
2842 #!+cdr-5
:truncate
)))
2844 ((and (member direction
'(:output
:io
))
2845 (not (member if-exists
'(:overwrite
:append
2846 #!+cdr-5
:truncate
))))
2848 (check-type if-does-not-exist
(member :create
:error nil
))
2849 (check-type if-exists
(member :new-version
:supersede
2850 :rename
:rename-and-delete
2853 #!+cdr-5
:truncate
))
2855 (labels ((fail (errno)
2856 (simple-file-perror "cannot open ~A" filespec errno
))
2857 (fail-if (boolean errno
)
2860 (return-from open-file nil
)))
2861 (open-bug (existsp) ;This hasn't happened yet, in fact.
2862 (bug "~&This can't happen. ~
2863 The file does~:[ not~;~] exist.~%
2865 IF-DOES-NOT-EXIST: ~A~%~
2867 existsp direction if-does-not-exist if-exists
))
2868 (compute-os-open-arguments (existsp)
2869 "Using the defaulted arguments to OPEN-FILE in the
2870 lexical environment and a boolean that's true if
2871 and only if the file exists, compute the arguments
2872 to the OS's opening syscall."
2873 ;; Remember that IF-EXISTS actions are to be carried out
2874 ;; only when the file already exists, so, e.g., :I-D-N-E
2875 ;; :CREATE :I-E :APPEND doesn't get :APPEND's special
2876 ;; treatment if the file doesn't yet exist. Note also
2877 ;; that because we determine whether the file exists
2878 ;; before calling this, this code only gets run in case
2879 ;; we actually try opening something, e.g., we don't run
2880 ;; this when the file does not exist and
2881 ;; IF-DOES-NOT-EXIST is NIL or :ERROR.
2882 (merge-os-open-arguments
2883 #!-win32-uses-file-handles
2884 (%make-os-open-arguments
2887 (:input sb
!unix
:o_rdonly
)
2888 (:probe sb
!unix
:o_rdonly
)
2889 (:output sb
!unix
:o_wronly
)
2890 (:io sb
!unix
:o_rdwr
))
2892 (if (member direction
'(:output
:io
))
2894 (:append sb
!unix
:o_append
)
2895 ((:rename
:rename-and-delete
)
2896 (logior sb
!unix
:o_creat sb
!unix
:o_excl
))
2898 #!+open-supersede-is-rename-and-delete
2899 (logior sb
!unix
:o_creat sb
!unix
:o_excl
)
2900 #!-open-supersede-is-rename-and-delete
2903 (:truncate sb
!unix
:o_trunc
)
2906 (if (eq if-does-not-exist
:create
)
2907 (logior sb
!unix
:o_creat sb
!unix
:o_excl
)
2909 ;; Win32's CreateFile seems to be able to do all the
2910 ;; basic stuff that we have POSIX open() do; it just
2911 ;; organizes the details differently.
2912 #!+win32-uses-file-handles
2913 (%make-os-open-arguments
2916 (:input sb
!win32
:generic_read
)
2918 (:output
(if (and existsp
(eq if-exists
:append
))
2919 (logandc2 sb
!win32
:generic_write
2920 sb
!win32
:file_write_data
)
2921 sb
!win32
:generic_write
))
2922 (:io
(logior sb
!win32
:generic_read
2923 (if (and existsp
(eq if-exists
:append
))
2924 (logandc2 sb
!win32
:generic_write
2925 sb
!win32
:file_write_data
)
2926 sb
!win32
:generic_write
))))
2927 :creation-disposition
2929 (if (member direction
'(:output
:io
))
2931 ((:overwrite
:append
) sb
!win32
:open_existing
)
2932 ((:rename
:rename-and-delete
)
2933 sb
!win32
:create_new
)
2934 #!-open-supersede-is-rename-and-delete
2935 (:supersede sb
!win32
:truncate_existing
)
2936 #!+open-supersede-is-rename-and-delete
2937 (:supersede sb
!win32
:create_new
)
2939 (:truncate sb
!win32
:truncate_existing
))
2940 sb
!win32
:open_existing
)
2941 (if (eq if-does-not-exist
:create
)
2945 (random-pathname (pathname)
2946 (parse-native-namestring
2948 (concatenate 'string
(native-namestring pathname
) "-XXXXXX"))
2949 (pathname-host pathname
)))
2950 (ensure-extant-nondirectory-file (truename)
2951 (multiple-value-bind (targetp errno ino mode
)
2952 (sb!unix
:unix-stat
(native-namestring truename
))
2953 (declare (ignore ino
))
2956 (when (= (logand mode sb
!unix
:s-ifmt
) sb
!unix
:s-ifdir
)
2957 (fail sb
!unix
:eisdir
))))
2958 (%open
(truename os-open-arguments
)
2959 (locally (declare (special *file-descriptor
*))
2960 (setf *file-descriptor
* nil
)
2961 (let ((filename (native-namestring truename
)))
2962 (uninterruptibly-bind-and-protect (file-descriptor errno
)
2963 (os-open filename os-open-arguments
)
2966 (setf *file-descriptor
* file-descriptor
2967 file-descriptor nil
)
2971 (when file-descriptor
2972 (close-descriptor file-descriptor t
)
2973 (setf *file-descriptor
* nil
)
2974 #|
(when (eq if-does-not-exist
:create
)
2975 (delete-file truename
))|
#)))))
2977 (let ((pathname (merge-pathnames filespec
)))
2978 (if (eq (car (pathname-directory pathname
)) :absolute
)
2980 (if (typep pathname
'logical-pathname
)
2981 ;; Relative logical pathnames can, in principle,
2982 ;; have translations (though programmers who
2983 ;; write programs that rely on such translations
2984 ;; would steal sheep).
2986 ;; Note that getcwd(3) can fail on traditional
2987 ;; Unices. In that case, we can't get a full
2988 ;; pathname for the user, even if we can open the
2990 (let ((cwd (ignore-errors
2991 #!+unix
(sb!unix
:posix-getcwd
)
2992 #!+win32
(sb!win32
:get-current-directory
)))
2993 (host (pathname-host filespec
)))
2996 (parse-native-namestring
2997 cwd host nil
:as-directory t
)))
2998 (merge-pathnames pathname cwd-pathname
))
3001 (not (not (member direction
'(:input
:probe
:io
)))))
3003 (not (not (member direction
'(:io
:output
)))))
3004 (create-beside (truename os-open-arguments
)
3005 (loop for random-pathname
= (random-pathname truename
)
3007 (%open random-pathname os-open-arguments
)
3008 (file-exists () nil
))
3011 (merged-pathname) random-pathname
3012 ;; For files created under a random
3013 ;; name, eventually call RENAME-FILE,
3014 ;; which implicitly merges. So we
3015 ;; reparse the unparsed TRUENAME in
3016 ;; order to normalize pathnames like
3017 ;; #S(pathname :name "abc.def" :type
3018 ;; nil), which will rename wrong with
3019 ;; the parse of "abc.def-XXXXXX".
3020 (parse-native-namestring
3021 (native-namestring truename
)
3022 (pathname-host truename
))
3023 (input-p) (output-p)
3024 (if (eq direction
:probe
) #'close
3025 #!-open-lazy-file-disposition
3026 #'open-eager-rename
)
3027 ;; Note: if :NEW-VERSION is ever
3028 ;; changed to create a new file when
3029 ;; one already exists, decide whether
3030 ;; it should be like :RENAME or
3031 ;; :RENAME-AND-DELETE, and then
3032 ;; change both these two forms.
3033 #!-open-lazy-file-disposition
3034 (if (eq if-exists
:rename
)
3035 #'close-rename-altname
3036 #'close-delete-altname
)
3037 #!+open-lazy-file-disposition
3038 (if (eq if-exists
:rename
)
3040 #'close-lazy-supersede
)))))
3041 (open-extant (truename os-open-arguments
)
3042 (when (%open truename os-open-arguments
)
3043 (values (merged-pathname) truename nil
3044 (input-p) (output-p)
3045 (cond ((eq direction
:probe
) #'close
)
3046 ((and (member direction
'(:output
:io
))
3047 (eq if-exists
:append
))
3048 #'open-if-exists-append
))
3049 ;; Bizarre, unnecessary
3050 ;; historical behavior.
3051 #|
#!-open-supersede-is-rename-and-delete
3052 (if (and (member direction
'(:output
:io
))
3053 (eq if-exists
:supersede
))
3054 #'close-delete-pathname
)|
#)))
3055 #!-open-lazy-file-disposition
3056 (create-in-place (truename os-open-arguments
)
3057 (when (%open truename os-open-arguments
)
3058 (values (merged-pathname) truename nil
3059 (input-p) (output-p)
3060 (if (eq direction
:probe
) #'close
)
3061 #'close-abort-delete
)))
3062 ;; On Windows, we can't generally rename a file while it's
3063 ;; open, so we ensure an existing file is out of the way
3064 ;; and create in place.
3065 #!+(and win32
(not open-lazy-file-disposition
))
3066 (win32-lossy-create-beside (truename os-open-arguments
)
3067 (with-temporary-name-for-file (temp-name truename
)
3068 (ignore-errors (delete-file truename
))
3069 (when (%open truename os-open-arguments
)
3070 (values (merged-pathname) truename temp-name
3071 (input-p) (output-p)
3072 nil
(if (eq if-exists
:rename
)
3073 #'close-rename-altname
3074 #'close-delete-altname
))))))
3075 (let* ((truename (handler-case (probe-file filespec
)
3077 (if (eq if-does-not-exist nil
)
3078 (return-from open-file nil
)
3081 ;; We know the file exists.
3082 (cond ((or (member direction
'(:input
:probe
))
3084 '(:overwrite
:append
3086 #!-open-supersede-is-rename-and-delete
3088 (open-extant truename
(compute-os-open-arguments t
)))
3089 ((and (member direction
'(:output
:io
))
3091 '(:rename
:rename-and-delete
3092 #!+open-supersede-is-rename-and-delete
3094 (ensure-extant-nondirectory-file truename
)
3095 #!-
(and win32
(not open-lazy-file-disposition
))
3096 (create-beside truename
(compute-os-open-arguments t
))
3097 #!+(and win32
(not open-lazy-file-disposition
))
3098 (win32-lossy-create-beside
3099 truename
(compute-os-open-arguments t
)))
3100 ((and (member direction
'(:output
:io
))
3101 (member if-exists
'(:error nil
:new-version
)))
3102 (fail-if (member if-exists
'(:error
:new-version
))
3103 #!-win32-uses-file-handles
3105 #!+win32-uses-file-handles
3106 sb
!win32
:error_file_exists
))
3108 (let ((truename (translate-logical-pathname
3109 (merge-pathnames filespec
))))
3110 (cond ((eq if-does-not-exist
:create
)
3111 #!-open-lazy-file-disposition
3113 truename
(compute-os-open-arguments nil
))
3114 #!+open-lazy-file-disposition
3115 (create-beside truename
(compute-os-open-arguments nil
)))
3116 ((member if-does-not-exist
'(:error nil
))
3117 (fail-if (eq if-does-not-exist
:error
) sb
!unix
:enoent
))
3118 (t (open-bug nil
))))))))
3120 (defun open (pathspec &rest keys
3122 (direction :input
) (element-type 'character
)
3123 (if-exists nil if-exists-supplied-p
)
3124 (if-does-not-exist nil if-does-not-exist-supplied-p
)
3125 (external-format :default
))
3129 "Return a stream which reads from or writes to PATHSPEC.
3131 :DIRECTION - one of :INPUT, :OUTPUT, :IO, or :PROBE
3132 :ELEMENT-TYPE - the type of object to read or write, default BASE-CHAR
3133 :IF-EXISTS - one of :ERROR, :NEW-VERSION, :RENAME, :RENAME-AND-DELETE,
3134 :SUPERSEDE, :OVERWRITE, :APPEND, "
3135 #!+cdr-5
":TRUNCATE "
3137 :IF-DOES-NOT-EXIST - one of :ERROR, :CREATE or NIL."
3138 ;; FIXME: document things in the manual.
3139 #+nil
" See the manual for details.")
3140 (let (*file-descriptor
*) ;OPEN-FILE sets this.
3141 (declare (special *file-descriptor
*))
3142 (multiple-value-bind (pathname truename altname
3143 input output init-func close-func
)
3147 (if if-does-not-exist-supplied-p if-does-not-exist
'default
)
3148 (if if-exists-supplied-p if-exists
'default
)
3149 ;; Unix doesn't care about the element type, but Windows
3152 ;; We extract keyword arguments this way in order to force
3153 ;; the user to say :ALLOW-OTHER-KEYS T to take advantage of
3155 (apply #'make-os-open-arguments keys
))
3157 (when *file-descriptor
*
3158 (let ((stream (make-fd-stream *file-descriptor
*
3161 :element-type element-type
3162 :external-format external-format
3168 :after-close close-func
3170 ;; Now that the descriptor is stored in the stream,
3171 ;; CLOSE and the stream finalizer are responsible for
3172 ;; closing the descriptor.
3173 (setf *file-descriptor
* nil
)
3175 (handler-case (funcall init-func stream
)
3176 ;; If the INIT-FUNC fails (e.g., if the user tries an
3177 ;; :APPEND opening on an unseekable file), close the
3178 ;; stream now, rather than waiting until GC.
3180 (close stream
:abort t
)
3183 (when *file-descriptor
*
3184 (close-descriptor *file-descriptor
* t
))))))
3186 ;; SB-SIMPLE-STREAMS wants a hook for opening an FD-STREAM, but it
3187 ;; redefines OPEN, so rather than have it duplicate the above, we'll
3188 ;; give it this. Also, any other internal stuff that needs to get an
3189 ;; FD-STREAM with OPEN-like interface can use this.
3190 (setf (fdefinition 'open-fd-stream
) #'open
)
3192 ;; RUN-PROGRAM needs to create pipes, so ISTM to be better to hide the
3193 ;; differences between descriptors and handles here.
3194 (defun open-pipe (&key
(external-format :default
))
3195 (uninterruptibly-bind-and-protect (read/nil write
/errno
)
3196 #!-win32-uses-file-handles
3198 #!+win32-uses-file-handles
3199 (sb!win32
:create-pipe
3200 (sb!win32
:make-security-attributes nil
1) 0)
3201 ;; FIXME: this form is interruptible; do we end up returning a
3202 ;; stream that wraps a closed pipe in case of interrupt?
3204 (let (read-stream write-stream
)
3205 (setf read-stream
(make-fd-stream
3207 :name
(format nil
"input pipe ~D" read
/nil
)
3209 :element-type
:default
3210 :external-format external-format
)
3212 write-stream
(make-fd-stream
3213 write
/errno
:output t
3214 :name
(format nil
"output pipe ~D" write
/errno
)
3216 :element-type
:default
3217 :external-format external-format
)
3219 (values read-stream write-stream
))
3220 ;; FIXME: this can't be a FILE-ERROR, since there's no
3221 ;; pathname involved. STREAM-ERROR? IPC-ERROR?
3222 (error "can't create pipe: ~A"
3223 #!+win32-uses-file-handles
3224 (sb!win32
:get-last-error-message write
/errno
)
3225 #!-win32-uses-file-handles
3226 (strerror write
/errno
)))
3229 (close-descriptor read
/nil t
))
3231 (close-descriptor write
/errno t
)))))
3236 ;;; the stream connected to the controlling terminal, or NIL if there is none
3239 ;;; the stream connected to the standard input (file descriptor 0)
3242 ;;; the stream connected to the standard output (file descriptor 1)
3245 ;;; the stream connected to the standard error output (file descriptor 2)
3248 ;;; This is called when the cold load is first started up, and may also
3249 ;;; be called in an attempt to recover from nested errors.
3250 (defun stream-cold-init-or-reset ()
3252 (setf *terminal-io
* (make-synonym-stream '*tty
*))
3253 (setf *standard-output
* (make-synonym-stream '*stdout
*))
3254 (setf *standard-input
* (make-synonym-stream '*stdin
*))
3255 (setf *error-output
* (make-synonym-stream '*stderr
*))
3256 (setf *query-io
* (make-synonym-stream '*terminal-io
*))
3257 (setf *debug-io
* *query-io
*)
3258 (setf *trace-output
* *standard-output
*)
3261 (defun stream-deinit ()
3262 ;; Unbind to make sure we're not accidently dealing with it
3263 ;; before we're ready (or after we think it's been deinitialized).
3264 (with-available-buffers-lock ()
3265 (without-package-locks
3266 (makunbound '*available-buffers
*))))
3268 ;;; This is called whenever a saved core is restarted.
3269 (defun stream-reinit (&optional init-buffers-p
)
3270 (when init-buffers-p
3271 (with-available-buffers-lock ()
3272 (aver (not (boundp '*available-buffers
*)))
3273 (setf *available-buffers
* nil
)))
3274 (multiple-value-bind (stdin stdout stderr
)
3275 #!-win32-uses-file-handles
(values 0 1 2)
3276 #!+win32-uses-file-handles
(sb!win32
:get-initial-handles
)
3277 #| FIXME
: what if some of these win32 handles is invalid? |
#
3278 (/primitive-print
"/got handles")
3282 (with-output-to-string (*error-output
*)
3285 stdin
:name
"standard input" :input t
:buffering
:line
3286 #!+win32
:external-format
3287 #!+win32
(sb!win32
::console-input-codepage
)))
3290 stdout
:name
"standard output" :output t
:buffering
:line
3291 #!+win32
:external-format
3292 #!+win32
(sb!win32
::console-output-codepage
)))
3295 stderr
:name
"standard error" :output t
:buffering
:line
3296 #!+win32
:external-format
3297 #!+win32
(sb!win32
::console-output-codepage
)))
3298 (/primitive-print
"/constructed *stdin*, *stdout*, *stderr*")
3299 (let* ((ttyname #.
(coerce "/dev/tty" 'simple-base-string
))
3300 (tty (sb!unix
:unix-open ttyname sb
!unix
:o_rdwr
#o666
)))
3304 :name
"the terminal"
3309 (setf *tty
* (make-two-way-stream *stdin
* *stdout
*))))
3310 (princ (get-output-stream-string *error-output
*) *stderr
*)))
3315 ;;; the Unix way to beep
3316 (defun beep (stream)
3317 (write-char (code-char bell-char-code
) stream
)
3318 (finish-output stream
))