2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[IOHandle]{Module @IOHandle@}
7 This module defines Haskell {\em handles} and the basic operations
8 which are supported for them.
18 import ArrBase ( ByteArray(..) )
19 import PrelRead ( Read )
29 %*********************************************************
31 \subsection{Types @FilePath@, @Handle@, @Handle__@}
33 %*********************************************************
36 type FilePath = String
38 #if defined(__CONCURRENT_HASKELL__)
39 type Handle = MVar Handle__
46 type Handle = MutableVar RealWorld Handle__
48 newHandle v = stToIO (newVar v)
49 readHandle h = stToIO (readVar h)
50 writeHandle h v = stToIO (writeVar h v)
52 #endif {- __CONCURRENT_HASKELL__ -}
57 | SemiClosedHandle Addr (Addr, Int)
58 | ReadHandle Addr (Maybe BufferMode) Bool
59 | WriteHandle Addr (Maybe BufferMode) Bool
60 | AppendHandle Addr (Maybe BufferMode) Bool
61 | ReadWriteHandle Addr (Maybe BufferMode) Bool
63 instance Eq Handle{-partain:????-}
65 {-# INLINE newHandle #-}
66 {-# INLINE readHandle #-}
67 {-# INLINE writeHandle #-}
69 newHandle :: Handle__ -> IO Handle
70 readHandle :: Handle -> IO Handle__
71 writeHandle :: Handle -> Handle__ -> IO ()
74 %*********************************************************
76 \subsection{Functions}
78 %*********************************************************
81 filePtr :: Handle__ -> Addr
82 filePtr (SemiClosedHandle fp _) = fp
83 filePtr (ReadHandle fp _ _) = fp
84 filePtr (WriteHandle fp _ _) = fp
85 filePtr (AppendHandle fp _ _) = fp
86 filePtr (ReadWriteHandle fp _ _) = fp
88 bufferMode :: Handle__ -> Maybe BufferMode
89 bufferMode (ReadHandle _ m _) = m
90 bufferMode (WriteHandle _ m _) = m
91 bufferMode (AppendHandle _ m _) = m
92 bufferMode (ReadWriteHandle _ m _) = m
94 markHandle :: Handle__ -> Handle__
95 markHandle h@(ReadHandle fp m b)
97 | otherwise = ReadHandle fp m True
98 markHandle h@(WriteHandle fp m b)
100 | otherwise = WriteHandle fp m True
101 markHandle h@(AppendHandle fp m b)
103 | otherwise = AppendHandle fp m True
104 markHandle h@(ReadWriteHandle fp m b)
106 | otherwise = ReadWriteHandle fp m True
109 -------------------------------------------
111 %*********************************************************
113 \subsection[StdHandles]{Standard handles}
115 %*********************************************************
117 Three handles are allocated during program initialisation. The first
118 two manage input or output from the Haskell program's standard input
119 or output channel respectively. The third manages output to the
120 standard error channel. These handles are initially open.
123 stdin, stdout, stderr :: Handle
125 stdin = unsafePerformPrimIO (
126 _ccall_ getLock (``stdin''::Addr) 0 >>= \ rc ->
128 0 -> new_handle ClosedHandle
129 1 -> new_handle (ReadHandle ``stdin'' Nothing False)
130 _ -> constructError "stdin" >>= \ ioError ->
131 new_handle (ErrorHandle ioError)
136 new_handle x = ioToST (newHandle x)
138 stdout = unsafePerformPrimIO (
139 _ccall_ getLock (``stdout''::Addr) 1 >>= \ rc ->
141 0 -> new_handle ClosedHandle
142 1 -> new_handle (WriteHandle ``stdout'' Nothing False)
143 _ -> constructError "stdout" >>= \ ioError ->
144 new_handle (ErrorHandle ioError)
149 new_handle x = ioToST (newHandle x)
151 stderr = unsafePerformPrimIO (
152 _ccall_ getLock (``stderr''::Addr) 1 >>= \ rc ->
154 0 -> new_handle ClosedHandle
155 1 -> new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)
156 _ -> constructError "stderr" >>= \ ioError ->
157 new_handle (ErrorHandle ioError)
162 new_handle x = ioToST (newHandle x)
165 %*********************************************************
167 \subsection[OpeningClosing]{Opening and Closing Files}
169 %*********************************************************
172 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
173 deriving (Eq, Ord, Ix, Enum, Read, Show)
175 openFile :: FilePath -> IOMode -> IO Handle
178 stToIO (_ccall_ openFile f m') >>= \ ptr ->
179 if ptr /= ``NULL'' then
180 newHandle (htype ptr Nothing False)
182 stToIO (constructError "openFile") >>= \ ioError ->
184 improved_error -- a HACK, I guess
186 AlreadyExists msg -> AlreadyExists (msg ++ ": " ++ f)
187 NoSuchThing msg -> NoSuchThing (msg ++ ": " ++ f)
188 PermissionDenied msg -> PermissionDenied (msg ++ ": " ++ f)
197 ReadWriteMode -> "r+"
200 ReadMode -> ReadHandle
201 WriteMode -> WriteHandle
202 AppendMode -> AppendHandle
203 ReadWriteMode -> ReadWriteHandle
206 Computation $openFile file mode$ allocates and returns a new, open
207 handle to manage the file {\em file}. It manages input if {\em mode}
208 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
209 and both input and output if mode is $ReadWriteMode$.
211 If the file does not exist and it is opened for output, it should be
212 created as a new file. If {\em mode} is $WriteMode$ and the file
213 already exists, then it should be truncated to zero length. The
214 handle is positioned at the end of the file if {\em mode} is
215 $AppendMode$, and otherwise at the beginning (in which case its
216 internal position is 0).
218 Implementations should enforce, locally to the Haskell process,
219 multiple-reader single-writer locking on files, which is to say that
220 there may either be many handles on the same file which manage input,
221 or just one handle on the file which manages output. If any open or
222 semi-closed handle is managing a file for output, no new handle can be
223 allocated for that file. If any open or semi-closed handle is
224 managing a file for input, new handles can only be allocated if they
225 do not manage output.
227 Two files are the same if they have the same absolute name. An
228 implementation is free to impose stricter conditions.
231 hClose :: Handle -> IO ()
234 readHandle handle >>= \ htype ->
235 writeHandle handle ClosedHandle >>
237 ErrorHandle ioError ->
240 fail (IllegalOperation "handle is closed")
241 SemiClosedHandle fp (buf,_) ->
242 (if buf /= ``NULL'' then
245 returnPrimIO ()) `thenIO_Prim` \ () ->
246 if fp /= ``NULL'' then
247 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
251 constructErrorAndFail "hClose"
255 _ccall_ closeFile (filePtr other) `thenIO_Prim` \ rc ->
259 constructErrorAndFail "hClose"
262 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
263 computation finishes, any items buffered for output and not already
264 sent to the operating system are flushed as for $flush$.
266 %*********************************************************
268 \subsection[EOF]{Detecting the End of Input}
270 %*********************************************************
273 For a handle {\em hdl} which attached to a physical file, $hFileSize
274 hdl$ returns the size of {\em hdl} in terms of the number of items
275 which can be read from {\em hdl}.
278 hFileSize :: Handle -> IO Integer
280 readHandle handle >>= \ htype ->
282 ErrorHandle ioError ->
283 writeHandle handle htype >>
286 writeHandle handle htype >>
287 fail (IllegalOperation "handle is closed")
288 SemiClosedHandle _ _ ->
289 writeHandle handle htype >>
290 fail (IllegalOperation "handle is closed")
292 -- HACK! We build a unique MP_INT of the right shape to hold
293 -- a single unsigned word, and we let the C routine change the data bits
294 _casm_ ``%r = 1;'' `thenIO_Prim` \ (I# hack#) ->
295 case int2Integer# hack# of
296 result@(J# _ _ d#) ->
298 bogus_bounds = (error "fileSize"::(Int,Int))
300 _ccall_ fileSize (filePtr other) (ByteArray bogus_bounds d#)
301 `thenIO_Prim` \ rc ->
302 writeHandle handle htype >>
306 constructErrorAndFail "hFileSize"
309 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
310 $True$ if no further input can be taken from {\em hdl} or for a
311 physical file, if the current I/O position is equal to the length of
312 the file. Otherwise, it returns $False$.
315 hIsEOF :: Handle -> IO Bool
317 readHandle handle >>= \ htype ->
319 ErrorHandle ioError ->
320 writeHandle handle htype >>
323 writeHandle handle htype >>
324 fail (IllegalOperation "handle is closed")
325 SemiClosedHandle _ _ ->
326 writeHandle handle htype >>
327 fail (IllegalOperation "handle is closed")
329 writeHandle handle htype >>
330 fail (IllegalOperation "handle is not open for reading")
331 AppendHandle _ _ _ ->
332 writeHandle handle htype >>
333 fail (IllegalOperation "handle is not open for reading")
335 _ccall_ fileEOF (filePtr other) `thenIO_Prim` \ rc ->
336 writeHandle handle (markHandle htype) >>
340 _ -> constructErrorAndFail "hIsEOF"
346 %*********************************************************
348 \subsection[Buffering]{Buffering Operations}
350 %*********************************************************
352 Three kinds of buffering are supported: line-buffering,
353 block-buffering or no-buffering. These modes have the following effects.
354 For output, items are written out from the internal buffer
355 according to the buffer mode:
357 \item[line-buffering] the entire output buffer is written
358 out whenever a newline is output, the output buffer overflows,
359 a flush is issued, or the handle is closed.
361 \item[block-buffering] the entire output buffer is written out whenever
362 it overflows, a flush is issued, or the handle
365 \item[no-buffering] output is written immediately, and never stored
366 in the output buffer.
369 The output buffer is emptied as soon as it has been written out.
371 Similarly, input occurs according to the buffer mode for handle {\em hdl}.
373 \item[line-buffering] when the input buffer for {\em hdl} is not empty,
374 the next item is obtained from the buffer;
375 otherwise, when the input buffer is empty,
376 characters up to and including the next newline
377 character are read into the buffer. No characters
378 are available until the newline character is
380 \item[block-buffering] when the input buffer for {\em hdl} becomes empty,
381 the next block of data is read into this buffer.
382 \item[no-buffering] the next input item is read and returned.
384 For most implementations, physical files will normally be block-buffered
385 and terminals will normally be line-buffered.
388 data BufferMode = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
389 deriving (Eq, Ord, Read, Show)
392 Computation $hSetBuffering hdl mode$ sets the mode of buffering for
393 handle {\em hdl} on subsequent reads and writes.
397 If {\em mode} is $LineBuffering$, line-buffering should be
400 If {\em mode} is $BlockBuffering$ {\em size}, then block-buffering
401 should be enabled if possible. The size of the buffer is {\em n} items
402 if {\em size} is $Just${\em n} and is otherwise implementation-dependent.
404 If {\em mode} is $NoBuffering$, then buffering is disabled if possible.
407 If the buffer mode is changed from $BlockBuffering$ or $LineBuffering$
408 to $NoBuffering$, then any items in the output buffer are written to
409 the device, and any items in the input buffer are discarded. The
410 default buffering mode when a handle is opened is
411 implementation-dependent and may depend on the object which is
412 attached to that handle.
415 hSetBuffering :: Handle -> BufferMode -> IO ()
417 hSetBuffering handle mode =
419 (BlockBuffering (Just n))
420 | n <= 0 -> fail (InvalidArgument "illegal buffer size")
422 readHandle handle >>= \ htype ->
423 if isMarked htype then
424 writeHandle handle htype >>
425 fail (UnsupportedOperation "can't set buffering for a dirty handle")
428 ErrorHandle ioError ->
429 writeHandle handle htype >>
432 writeHandle handle htype >>
433 fail (IllegalOperation "handle is closed")
434 SemiClosedHandle _ _ ->
435 writeHandle handle htype >>
436 fail (IllegalOperation "handle is closed")
438 _ccall_ setBuffering (filePtr other) bsize
439 `thenIO_Prim` \ rc ->
441 writeHandle handle ((hcon other) (filePtr other) (Just mode) True)
445 writeHandle handle htype >>
446 constructErrorAndFail "hSetBuffering"
449 isMarked :: Handle__ -> Bool
450 isMarked (ReadHandle fp m b) = b
451 isMarked (WriteHandle fp m b) = b
452 isMarked (AppendHandle fp m b) = b
453 isMarked (ReadWriteHandle fp m b) = b
459 BlockBuffering Nothing -> -2
460 BlockBuffering (Just n) -> n
462 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
463 hcon (ReadHandle _ _ _) = ReadHandle
464 hcon (WriteHandle _ _ _) = WriteHandle
465 hcon (AppendHandle _ _ _) = AppendHandle
466 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
469 Computation $flush hdl$ causes any items buffered for output in handle
470 {\em hdl} to be sent immediately to the operating system.
473 hFlush :: Handle -> IO ()
475 readHandle handle >>= \ htype ->
477 ErrorHandle ioError ->
478 writeHandle handle htype >>
481 writeHandle handle htype >>
482 fail (IllegalOperation "handle is closed")
483 SemiClosedHandle _ _ ->
484 writeHandle handle htype >>
485 fail (IllegalOperation "handle is closed")
487 _ccall_ flushFile (filePtr other) `thenIO_Prim` \ rc ->
488 writeHandle handle (markHandle htype) >>
492 constructErrorAndFail "hFlush"
496 %*********************************************************
498 \subsection[Seeking]{Repositioning Handles}
500 %*********************************************************
503 data HandlePosn = HandlePosn Handle Int
505 instance Eq HandlePosn{-partain-}
507 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
508 deriving (Eq, Ord, Ix, Enum, Read, Show)
511 Computation $hGetPosn hdl$ returns the current I/O
512 position of {\em hdl} as an abstract position. Computation
513 $hSetPosn p$ sets the position of {\em hdl}
514 to a previously obtained position {\em p}.
517 hGetPosn :: Handle -> IO HandlePosn
519 readHandle handle >>= \ htype ->
521 ErrorHandle ioError ->
522 writeHandle handle htype >>
525 writeHandle handle htype >>
526 fail (IllegalOperation "handle is closed")
527 SemiClosedHandle _ _ ->
528 writeHandle handle htype >>
529 fail (IllegalOperation "handle is closed")
531 _ccall_ getFilePosn (filePtr other) `thenIO_Prim` \ posn ->
532 writeHandle handle htype >>
534 return (HandlePosn handle posn)
536 constructErrorAndFail "hGetPosn"
538 hSetPosn :: HandlePosn -> IO ()
539 hSetPosn (HandlePosn handle posn) =
540 readHandle handle >>= \ htype ->
542 ErrorHandle ioError ->
543 writeHandle handle htype >>
546 writeHandle handle htype >>
547 fail (IllegalOperation "handle is closed")
548 SemiClosedHandle _ _ ->
549 writeHandle handle htype >>
550 fail (IllegalOperation "handle is closed")
551 AppendHandle _ _ _ ->
552 writeHandle handle htype >>
553 fail (IllegalOperation "handle is not seekable")
555 _ccall_ setFilePosn (filePtr other) posn `thenIO_Prim` \ rc ->
556 writeHandle handle (markHandle htype) >>
560 constructErrorAndFail "hSetPosn"
563 Computation $hSeek hdl mode i$ sets the position of handle
564 {\em hdl} depending on $mode$. If {\em mode} is
566 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
567 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
568 the current position.
569 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
571 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
572 the beginning of the file.
575 Some handles may not be seekable $hIsSeekable$, or only support a
576 subset of the possible positioning operations (e.g. it may only be
577 possible to seek to the end of a tape, or to a positive offset from
578 the beginning or current position).
580 It is not possible to set a negative I/O position, or for a physical
581 file, an I/O position beyond the current end-of-file.
584 hSeek :: Handle -> SeekMode -> Integer -> IO ()
585 hSeek handle mode offset@(J# _ s# d#) =
586 readHandle handle >>= \ htype ->
588 ErrorHandle ioError ->
589 writeHandle handle htype >>
592 writeHandle handle htype >>
593 fail (IllegalOperation "handle is closed")
594 SemiClosedHandle _ _ ->
595 writeHandle handle htype >>
596 fail (IllegalOperation "handle is closed")
597 AppendHandle _ _ _ ->
598 writeHandle handle htype >>
599 fail (IllegalOperation "handle is not seekable")
601 _ccall_ seekFile (filePtr other) whence (I# s#) (ByteArray (0,0) d#)
602 `thenIO_Prim` \ rc ->
603 writeHandle handle (markHandle htype) >>
607 constructErrorAndFail "hSeek"
610 whence = case mode of
611 AbsoluteSeek -> ``SEEK_SET''
612 RelativeSeek -> ``SEEK_CUR''
613 SeekFromEnd -> ``SEEK_END''
616 %*********************************************************
618 \subsection[Query]{Handle Properties}
620 %*********************************************************
622 A number of operations return information about the properties of a
623 handle. Each of these operations returns $True$ if the
624 handle has the specified property, and $False$
627 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
628 {\em hdl} is not block-buffered. Otherwise it returns
629 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
630 $( Just n )$ for block-buffering of {\em n} bytes.
633 hIsOpen :: Handle -> IO Bool
635 readHandle handle >>= \ htype ->
637 ErrorHandle ioError ->
638 writeHandle handle htype >>
641 writeHandle handle htype >>
643 SemiClosedHandle _ _ ->
644 writeHandle handle htype >>
647 writeHandle handle htype >>
650 hIsClosed :: Handle -> IO Bool
652 readHandle handle >>= \ htype ->
654 ErrorHandle ioError ->
655 writeHandle handle htype >>
658 writeHandle handle htype >>
661 writeHandle handle htype >>
664 hIsReadable :: Handle -> IO Bool
666 readHandle handle >>= \ htype ->
668 ErrorHandle ioError ->
669 writeHandle handle htype >>
672 writeHandle handle htype >>
673 fail (IllegalOperation "handle is closed")
674 SemiClosedHandle _ _ ->
675 writeHandle handle htype >>
676 fail (IllegalOperation "handle is closed")
678 writeHandle handle htype >>
679 return (isReadable other)
681 isReadable (ReadHandle _ _ _) = True
682 isReadable (ReadWriteHandle _ _ _) = True
685 hIsWritable :: Handle -> IO Bool
687 readHandle handle >>= \ htype ->
689 ErrorHandle ioError ->
690 writeHandle handle htype >>
693 writeHandle handle htype >>
694 fail (IllegalOperation "handle is closed")
695 SemiClosedHandle _ _ ->
696 writeHandle handle htype >>
697 fail (IllegalOperation "handle is closed")
699 writeHandle handle htype >>
700 return (isWritable other)
702 isWritable (AppendHandle _ _ _) = True
703 isWritable (WriteHandle _ _ _) = True
704 isWritable (ReadWriteHandle _ _ _) = True
707 getBufferMode :: Handle__ -> PrimIO Handle__
708 getBufferMode htype =
709 case bufferMode htype of
710 Just x -> returnPrimIO htype
712 _ccall_ getBufferMode (filePtr htype) `thenPrimIO` \ rc ->
716 0 -> Just NoBuffering
717 -1 -> Just LineBuffering
718 -2 -> Just (BlockBuffering Nothing)
720 n -> Just (BlockBuffering (Just n))
722 returnPrimIO (case htype of
723 ReadHandle fp _ b -> ReadHandle fp mode b
724 WriteHandle fp _ b -> WriteHandle fp mode b
725 AppendHandle fp _ b -> AppendHandle fp mode b
726 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
728 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
729 hIsBlockBuffered handle =
730 readHandle handle >>= \ htype ->
732 ErrorHandle ioError ->
733 writeHandle handle htype >>
736 writeHandle handle htype >>
737 fail (IllegalOperation "handle is closed")
738 SemiClosedHandle _ _ ->
739 writeHandle handle htype >>
740 fail (IllegalOperation "handle is closed")
742 getBufferMode other `thenIO_Prim` \ other ->
743 case bufferMode other of
744 Just (BlockBuffering size) ->
745 writeHandle handle other >>
748 writeHandle handle other >>
749 return (False, Nothing)
751 constructErrorAndFail "hIsBlockBuffered"
753 hIsLineBuffered :: Handle -> IO Bool
754 hIsLineBuffered handle =
755 readHandle handle >>= \ htype ->
757 ErrorHandle ioError ->
758 writeHandle handle htype >>
761 writeHandle handle htype >>
762 fail (IllegalOperation "handle is closed")
763 SemiClosedHandle _ _ ->
764 writeHandle handle htype >>
765 fail (IllegalOperation "handle is closed")
767 getBufferMode other `thenIO_Prim` \ other ->
768 case bufferMode other of
769 Just LineBuffering ->
770 writeHandle handle other >>
773 writeHandle handle other >>
776 constructErrorAndFail "hIsLineBuffered"
778 hIsNotBuffered :: Handle -> IO Bool
779 hIsNotBuffered handle =
780 readHandle handle >>= \ htype ->
782 ErrorHandle ioError ->
783 writeHandle handle htype >>
786 writeHandle handle htype >>
787 fail (IllegalOperation "handle is closed")
788 SemiClosedHandle _ _ ->
789 writeHandle handle htype >>
790 fail (IllegalOperation "handle is closed")
792 getBufferMode other `thenIO_Prim` \ other ->
793 case bufferMode other of
795 writeHandle handle other >>
798 writeHandle handle other >>
801 constructErrorAndFail "hIsNotBuffered"
803 hGetBuffering :: Handle -> IO BufferMode
805 readHandle hndl >>= \ htype ->
807 ErrorHandle ioError ->
808 writeHandle hndl htype >>
811 writeHandle hndl htype >>
812 fail (IllegalOperation "handle is closed")
813 SemiClosedHandle _ _ ->
814 writeHandle hndl htype >>
815 fail (IllegalOperation "handle is closed")
817 getBufferMode other `thenIO_Prim` \ other ->
818 case bufferMode other of
820 writeHandle hndl other >>
823 constructErrorAndFail "hGetBuffering"
825 hIsSeekable :: Handle -> IO Bool
827 readHandle handle >>= \ htype ->
829 ErrorHandle ioError ->
830 writeHandle handle htype >>
833 writeHandle handle htype >>
834 fail (IllegalOperation "handle is closed")
835 SemiClosedHandle _ _ ->
836 writeHandle handle htype >>
837 fail (IllegalOperation "handle is closed")
838 AppendHandle _ _ _ ->
839 writeHandle handle htype >>
842 _ccall_ seekFileP (filePtr other) `thenIO_Prim` \ rc ->
843 writeHandle handle htype >>
847 _ -> constructErrorAndFail "hIsSeekable"
851 %*********************************************************
853 \subsection{Miscellaneous}
855 %*********************************************************
857 These two functions are meant to get things out of @IOErrors@. They don't!
860 ioeGetFileName :: IOError -> Maybe FilePath
861 ioeGetHandle :: IOError -> Maybe Handle
864 ioeGetHandle _ = Nothing -- a stub, essentially
865 ioeGetFileName _ = Nothing -- a stub, essentially