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.
13 {-# OPTIONS -fno-implicit-prelude #-}
19 import ArrBase ( ByteArray(..) )
20 import PrelRead ( Read )
30 %*********************************************************
32 \subsection{Types @FilePath@, @Handle@, @Handle__@}
34 %*********************************************************
37 type FilePath = String
39 #if defined(__CONCURRENT_HASKELL__)
40 type Handle = MVar Handle__
47 type Handle = MutableVar RealWorld Handle__
49 newHandle v = stToIO (newVar v)
50 readHandle h = stToIO (readVar h)
51 writeHandle h v = stToIO (writeVar h v)
53 #endif {- __CONCURRENT_HASKELL__ -}
58 | SemiClosedHandle Addr (Addr, Int)
59 | ReadHandle Addr (Maybe BufferMode) Bool
60 | WriteHandle Addr (Maybe BufferMode) Bool
61 | AppendHandle Addr (Maybe BufferMode) Bool
62 | ReadWriteHandle Addr (Maybe BufferMode) Bool
64 instance Eq Handle{-partain:????-}
66 {-# INLINE newHandle #-}
67 {-# INLINE readHandle #-}
68 {-# INLINE writeHandle #-}
70 newHandle :: Handle__ -> IO Handle
71 readHandle :: Handle -> IO Handle__
72 writeHandle :: Handle -> Handle__ -> IO ()
75 %*********************************************************
77 \subsection{Functions}
79 %*********************************************************
82 filePtr :: Handle__ -> Addr
83 filePtr (SemiClosedHandle fp _) = fp
84 filePtr (ReadHandle fp _ _) = fp
85 filePtr (WriteHandle fp _ _) = fp
86 filePtr (AppendHandle fp _ _) = fp
87 filePtr (ReadWriteHandle fp _ _) = fp
89 bufferMode :: Handle__ -> Maybe BufferMode
90 bufferMode (ReadHandle _ m _) = m
91 bufferMode (WriteHandle _ m _) = m
92 bufferMode (AppendHandle _ m _) = m
93 bufferMode (ReadWriteHandle _ m _) = m
95 markHandle :: Handle__ -> Handle__
96 markHandle h@(ReadHandle fp m b)
98 | otherwise = ReadHandle fp m True
99 markHandle h@(WriteHandle fp m b)
101 | otherwise = WriteHandle fp m True
102 markHandle h@(AppendHandle fp m b)
104 | otherwise = AppendHandle fp m True
105 markHandle h@(ReadWriteHandle fp m b)
107 | otherwise = ReadWriteHandle fp m True
110 -------------------------------------------
112 %*********************************************************
114 \subsection[StdHandles]{Standard handles}
116 %*********************************************************
118 Three handles are allocated during program initialisation. The first
119 two manage input or output from the Haskell program's standard input
120 or output channel respectively. The third manages output to the
121 standard error channel. These handles are initially open.
124 stdin, stdout, stderr :: Handle
126 stdin = unsafePerformPrimIO (
127 _ccall_ getLock (``stdin''::Addr) 0 >>= \ rc ->
129 0 -> new_handle ClosedHandle
130 1 -> new_handle (ReadHandle ``stdin'' Nothing False)
131 _ -> constructError "stdin" >>= \ ioError ->
132 new_handle (ErrorHandle ioError)
137 new_handle x = ioToST (newHandle x)
139 stdout = unsafePerformPrimIO (
140 _ccall_ getLock (``stdout''::Addr) 1 >>= \ rc ->
142 0 -> new_handle ClosedHandle
143 1 -> new_handle (WriteHandle ``stdout'' Nothing False)
144 _ -> constructError "stdout" >>= \ ioError ->
145 new_handle (ErrorHandle ioError)
150 new_handle x = ioToST (newHandle x)
152 stderr = unsafePerformPrimIO (
153 _ccall_ getLock (``stderr''::Addr) 1 >>= \ rc ->
155 0 -> new_handle ClosedHandle
156 1 -> new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)
157 _ -> constructError "stderr" >>= \ ioError ->
158 new_handle (ErrorHandle ioError)
163 new_handle x = ioToST (newHandle x)
166 %*********************************************************
168 \subsection[OpeningClosing]{Opening and Closing Files}
170 %*********************************************************
173 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
174 deriving (Eq, Ord, Ix, Enum, Read, Show)
176 openFile :: FilePath -> IOMode -> IO Handle
179 stToIO (_ccall_ openFile f m') >>= \ ptr ->
180 if ptr /= ``NULL'' then
181 newHandle (htype ptr Nothing False)
183 stToIO (constructError "openFile") >>= \ ioError ->
185 improved_error -- a HACK, I guess
187 AlreadyExists msg -> AlreadyExists (msg ++ ": " ++ f)
188 NoSuchThing msg -> NoSuchThing (msg ++ ": " ++ f)
189 PermissionDenied msg -> PermissionDenied (msg ++ ": " ++ f)
198 ReadWriteMode -> "r+"
201 ReadMode -> ReadHandle
202 WriteMode -> WriteHandle
203 AppendMode -> AppendHandle
204 ReadWriteMode -> ReadWriteHandle
207 Computation $openFile file mode$ allocates and returns a new, open
208 handle to manage the file {\em file}. It manages input if {\em mode}
209 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
210 and both input and output if mode is $ReadWriteMode$.
212 If the file does not exist and it is opened for output, it should be
213 created as a new file. If {\em mode} is $WriteMode$ and the file
214 already exists, then it should be truncated to zero length. The
215 handle is positioned at the end of the file if {\em mode} is
216 $AppendMode$, and otherwise at the beginning (in which case its
217 internal position is 0).
219 Implementations should enforce, locally to the Haskell process,
220 multiple-reader single-writer locking on files, which is to say that
221 there may either be many handles on the same file which manage input,
222 or just one handle on the file which manages output. If any open or
223 semi-closed handle is managing a file for output, no new handle can be
224 allocated for that file. If any open or semi-closed handle is
225 managing a file for input, new handles can only be allocated if they
226 do not manage output.
228 Two files are the same if they have the same absolute name. An
229 implementation is free to impose stricter conditions.
232 hClose :: Handle -> IO ()
235 readHandle handle >>= \ htype ->
236 writeHandle handle ClosedHandle >>
238 ErrorHandle ioError ->
241 fail (IllegalOperation "handle is closed")
242 SemiClosedHandle fp (buf,_) ->
243 (if buf /= ``NULL'' then
246 returnPrimIO ()) `thenIO_Prim` \ () ->
247 if fp /= ``NULL'' then
248 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
252 constructErrorAndFail "hClose"
256 _ccall_ closeFile (filePtr other) `thenIO_Prim` \ rc ->
260 constructErrorAndFail "hClose"
263 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
264 computation finishes, any items buffered for output and not already
265 sent to the operating system are flushed as for $flush$.
267 %*********************************************************
269 \subsection[EOF]{Detecting the End of Input}
271 %*********************************************************
274 For a handle {\em hdl} which attached to a physical file, $hFileSize
275 hdl$ returns the size of {\em hdl} in terms of the number of items
276 which can be read from {\em hdl}.
279 hFileSize :: Handle -> IO Integer
281 readHandle handle >>= \ htype ->
283 ErrorHandle ioError ->
284 writeHandle handle htype >>
287 writeHandle handle htype >>
288 fail (IllegalOperation "handle is closed")
289 SemiClosedHandle _ _ ->
290 writeHandle handle htype >>
291 fail (IllegalOperation "handle is closed")
293 -- HACK! We build a unique MP_INT of the right shape to hold
294 -- a single unsigned word, and we let the C routine change the data bits
295 _casm_ ``%r = 1;'' `thenIO_Prim` \ (I# hack#) ->
296 case int2Integer# hack# of
297 result@(J# _ _ d#) ->
299 bogus_bounds = (error "fileSize"::(Int,Int))
301 _ccall_ fileSize (filePtr other) (ByteArray bogus_bounds d#)
302 `thenIO_Prim` \ rc ->
303 writeHandle handle htype >>
307 constructErrorAndFail "hFileSize"
310 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
311 $True$ if no further input can be taken from {\em hdl} or for a
312 physical file, if the current I/O position is equal to the length of
313 the file. Otherwise, it returns $False$.
316 hIsEOF :: Handle -> IO Bool
318 readHandle handle >>= \ htype ->
320 ErrorHandle ioError ->
321 writeHandle handle htype >>
324 writeHandle handle htype >>
325 fail (IllegalOperation "handle is closed")
326 SemiClosedHandle _ _ ->
327 writeHandle handle htype >>
328 fail (IllegalOperation "handle is closed")
330 writeHandle handle htype >>
331 fail (IllegalOperation "handle is not open for reading")
332 AppendHandle _ _ _ ->
333 writeHandle handle htype >>
334 fail (IllegalOperation "handle is not open for reading")
336 _ccall_ fileEOF (filePtr other) `thenIO_Prim` \ rc ->
337 writeHandle handle (markHandle htype) >>
341 _ -> constructErrorAndFail "hIsEOF"
347 %*********************************************************
349 \subsection[Buffering]{Buffering Operations}
351 %*********************************************************
353 Three kinds of buffering are supported: line-buffering,
354 block-buffering or no-buffering. These modes have the following effects.
355 For output, items are written out from the internal buffer
356 according to the buffer mode:
358 \item[line-buffering] the entire output buffer is written
359 out whenever a newline is output, the output buffer overflows,
360 a flush is issued, or the handle is closed.
362 \item[block-buffering] the entire output buffer is written out whenever
363 it overflows, a flush is issued, or the handle
366 \item[no-buffering] output is written immediately, and never stored
367 in the output buffer.
370 The output buffer is emptied as soon as it has been written out.
372 Similarly, input occurs according to the buffer mode for handle {\em hdl}.
374 \item[line-buffering] when the input buffer for {\em hdl} is not empty,
375 the next item is obtained from the buffer;
376 otherwise, when the input buffer is empty,
377 characters up to and including the next newline
378 character are read into the buffer. No characters
379 are available until the newline character is
381 \item[block-buffering] when the input buffer for {\em hdl} becomes empty,
382 the next block of data is read into this buffer.
383 \item[no-buffering] the next input item is read and returned.
385 For most implementations, physical files will normally be block-buffered
386 and terminals will normally be line-buffered.
389 data BufferMode = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
390 deriving (Eq, Ord, Read, Show)
393 Computation $hSetBuffering hdl mode$ sets the mode of buffering for
394 handle {\em hdl} on subsequent reads and writes.
398 If {\em mode} is $LineBuffering$, line-buffering should be
401 If {\em mode} is $BlockBuffering$ {\em size}, then block-buffering
402 should be enabled if possible. The size of the buffer is {\em n} items
403 if {\em size} is $Just${\em n} and is otherwise implementation-dependent.
405 If {\em mode} is $NoBuffering$, then buffering is disabled if possible.
408 If the buffer mode is changed from $BlockBuffering$ or $LineBuffering$
409 to $NoBuffering$, then any items in the output buffer are written to
410 the device, and any items in the input buffer are discarded. The
411 default buffering mode when a handle is opened is
412 implementation-dependent and may depend on the object which is
413 attached to that handle.
416 hSetBuffering :: Handle -> BufferMode -> IO ()
418 hSetBuffering handle mode =
420 (BlockBuffering (Just n))
421 | n <= 0 -> fail (InvalidArgument "illegal buffer size")
423 readHandle handle >>= \ htype ->
424 if isMarked htype then
425 writeHandle handle htype >>
426 fail (UnsupportedOperation "can't set buffering for a dirty handle")
429 ErrorHandle ioError ->
430 writeHandle handle htype >>
433 writeHandle handle htype >>
434 fail (IllegalOperation "handle is closed")
435 SemiClosedHandle _ _ ->
436 writeHandle handle htype >>
437 fail (IllegalOperation "handle is closed")
439 _ccall_ setBuffering (filePtr other) bsize
440 `thenIO_Prim` \ rc ->
442 writeHandle handle ((hcon other) (filePtr other) (Just mode) True)
446 writeHandle handle htype >>
447 constructErrorAndFail "hSetBuffering"
450 isMarked :: Handle__ -> Bool
451 isMarked (ReadHandle fp m b) = b
452 isMarked (WriteHandle fp m b) = b
453 isMarked (AppendHandle fp m b) = b
454 isMarked (ReadWriteHandle fp m b) = b
460 BlockBuffering Nothing -> -2
461 BlockBuffering (Just n) -> n
463 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
464 hcon (ReadHandle _ _ _) = ReadHandle
465 hcon (WriteHandle _ _ _) = WriteHandle
466 hcon (AppendHandle _ _ _) = AppendHandle
467 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
470 Computation $flush hdl$ causes any items buffered for output in handle
471 {\em hdl} to be sent immediately to the operating system.
474 hFlush :: Handle -> IO ()
476 readHandle handle >>= \ htype ->
478 ErrorHandle ioError ->
479 writeHandle handle htype >>
482 writeHandle handle htype >>
483 fail (IllegalOperation "handle is closed")
484 SemiClosedHandle _ _ ->
485 writeHandle handle htype >>
486 fail (IllegalOperation "handle is closed")
488 _ccall_ flushFile (filePtr other) `thenIO_Prim` \ rc ->
489 writeHandle handle (markHandle htype) >>
493 constructErrorAndFail "hFlush"
497 %*********************************************************
499 \subsection[Seeking]{Repositioning Handles}
501 %*********************************************************
504 data HandlePosn = HandlePosn Handle Int
506 instance Eq HandlePosn{-partain-}
508 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
509 deriving (Eq, Ord, Ix, Enum, Read, Show)
512 Computation $hGetPosn hdl$ returns the current I/O
513 position of {\em hdl} as an abstract position. Computation
514 $hSetPosn p$ sets the position of {\em hdl}
515 to a previously obtained position {\em p}.
518 hGetPosn :: Handle -> IO HandlePosn
520 readHandle handle >>= \ htype ->
522 ErrorHandle ioError ->
523 writeHandle handle htype >>
526 writeHandle handle htype >>
527 fail (IllegalOperation "handle is closed")
528 SemiClosedHandle _ _ ->
529 writeHandle handle htype >>
530 fail (IllegalOperation "handle is closed")
532 _ccall_ getFilePosn (filePtr other) `thenIO_Prim` \ posn ->
533 writeHandle handle htype >>
535 return (HandlePosn handle posn)
537 constructErrorAndFail "hGetPosn"
539 hSetPosn :: HandlePosn -> IO ()
540 hSetPosn (HandlePosn handle posn) =
541 readHandle handle >>= \ htype ->
543 ErrorHandle ioError ->
544 writeHandle handle htype >>
547 writeHandle handle htype >>
548 fail (IllegalOperation "handle is closed")
549 SemiClosedHandle _ _ ->
550 writeHandle handle htype >>
551 fail (IllegalOperation "handle is closed")
552 AppendHandle _ _ _ ->
553 writeHandle handle htype >>
554 fail (IllegalOperation "handle is not seekable")
556 _ccall_ setFilePosn (filePtr other) posn `thenIO_Prim` \ rc ->
557 writeHandle handle (markHandle htype) >>
561 constructErrorAndFail "hSetPosn"
564 Computation $hSeek hdl mode i$ sets the position of handle
565 {\em hdl} depending on $mode$. If {\em mode} is
567 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
568 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
569 the current position.
570 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
572 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
573 the beginning of the file.
576 Some handles may not be seekable $hIsSeekable$, or only support a
577 subset of the possible positioning operations (e.g. it may only be
578 possible to seek to the end of a tape, or to a positive offset from
579 the beginning or current position).
581 It is not possible to set a negative I/O position, or for a physical
582 file, an I/O position beyond the current end-of-file.
585 hSeek :: Handle -> SeekMode -> Integer -> IO ()
586 hSeek handle mode offset@(J# _ s# d#) =
587 readHandle handle >>= \ htype ->
589 ErrorHandle ioError ->
590 writeHandle handle htype >>
593 writeHandle handle htype >>
594 fail (IllegalOperation "handle is closed")
595 SemiClosedHandle _ _ ->
596 writeHandle handle htype >>
597 fail (IllegalOperation "handle is closed")
598 AppendHandle _ _ _ ->
599 writeHandle handle htype >>
600 fail (IllegalOperation "handle is not seekable")
602 _ccall_ seekFile (filePtr other) whence (I# s#) (ByteArray (0,0) d#)
603 `thenIO_Prim` \ rc ->
604 writeHandle handle (markHandle htype) >>
608 constructErrorAndFail "hSeek"
611 whence = case mode of
612 AbsoluteSeek -> ``SEEK_SET''
613 RelativeSeek -> ``SEEK_CUR''
614 SeekFromEnd -> ``SEEK_END''
617 %*********************************************************
619 \subsection[Query]{Handle Properties}
621 %*********************************************************
623 A number of operations return information about the properties of a
624 handle. Each of these operations returns $True$ if the
625 handle has the specified property, and $False$
628 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
629 {\em hdl} is not block-buffered. Otherwise it returns
630 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
631 $( Just n )$ for block-buffering of {\em n} bytes.
634 hIsOpen :: Handle -> IO Bool
636 readHandle handle >>= \ htype ->
638 ErrorHandle ioError ->
639 writeHandle handle htype >>
642 writeHandle handle htype >>
644 SemiClosedHandle _ _ ->
645 writeHandle handle htype >>
648 writeHandle handle htype >>
651 hIsClosed :: Handle -> IO Bool
653 readHandle handle >>= \ htype ->
655 ErrorHandle ioError ->
656 writeHandle handle htype >>
659 writeHandle handle htype >>
662 writeHandle handle htype >>
665 hIsReadable :: Handle -> IO Bool
667 readHandle handle >>= \ htype ->
669 ErrorHandle ioError ->
670 writeHandle handle htype >>
673 writeHandle handle htype >>
674 fail (IllegalOperation "handle is closed")
675 SemiClosedHandle _ _ ->
676 writeHandle handle htype >>
677 fail (IllegalOperation "handle is closed")
679 writeHandle handle htype >>
680 return (isReadable other)
682 isReadable (ReadHandle _ _ _) = True
683 isReadable (ReadWriteHandle _ _ _) = True
686 hIsWritable :: Handle -> IO Bool
688 readHandle handle >>= \ htype ->
690 ErrorHandle ioError ->
691 writeHandle handle htype >>
694 writeHandle handle htype >>
695 fail (IllegalOperation "handle is closed")
696 SemiClosedHandle _ _ ->
697 writeHandle handle htype >>
698 fail (IllegalOperation "handle is closed")
700 writeHandle handle htype >>
701 return (isWritable other)
703 isWritable (AppendHandle _ _ _) = True
704 isWritable (WriteHandle _ _ _) = True
705 isWritable (ReadWriteHandle _ _ _) = True
708 getBufferMode :: Handle__ -> PrimIO Handle__
709 getBufferMode htype =
710 case bufferMode htype of
711 Just x -> returnPrimIO htype
713 _ccall_ getBufferMode (filePtr htype) `thenPrimIO` \ rc ->
717 0 -> Just NoBuffering
718 -1 -> Just LineBuffering
719 -2 -> Just (BlockBuffering Nothing)
721 n -> Just (BlockBuffering (Just n))
723 returnPrimIO (case htype of
724 ReadHandle fp _ b -> ReadHandle fp mode b
725 WriteHandle fp _ b -> WriteHandle fp mode b
726 AppendHandle fp _ b -> AppendHandle fp mode b
727 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
729 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
730 hIsBlockBuffered handle =
731 readHandle handle >>= \ htype ->
733 ErrorHandle ioError ->
734 writeHandle handle htype >>
737 writeHandle handle htype >>
738 fail (IllegalOperation "handle is closed")
739 SemiClosedHandle _ _ ->
740 writeHandle handle htype >>
741 fail (IllegalOperation "handle is closed")
743 getBufferMode other `thenIO_Prim` \ other ->
744 case bufferMode other of
745 Just (BlockBuffering size) ->
746 writeHandle handle other >>
749 writeHandle handle other >>
750 return (False, Nothing)
752 constructErrorAndFail "hIsBlockBuffered"
754 hIsLineBuffered :: Handle -> IO Bool
755 hIsLineBuffered handle =
756 readHandle handle >>= \ htype ->
758 ErrorHandle ioError ->
759 writeHandle handle htype >>
762 writeHandle handle htype >>
763 fail (IllegalOperation "handle is closed")
764 SemiClosedHandle _ _ ->
765 writeHandle handle htype >>
766 fail (IllegalOperation "handle is closed")
768 getBufferMode other `thenIO_Prim` \ other ->
769 case bufferMode other of
770 Just LineBuffering ->
771 writeHandle handle other >>
774 writeHandle handle other >>
777 constructErrorAndFail "hIsLineBuffered"
779 hIsNotBuffered :: Handle -> IO Bool
780 hIsNotBuffered handle =
781 readHandle handle >>= \ htype ->
783 ErrorHandle ioError ->
784 writeHandle handle htype >>
787 writeHandle handle htype >>
788 fail (IllegalOperation "handle is closed")
789 SemiClosedHandle _ _ ->
790 writeHandle handle htype >>
791 fail (IllegalOperation "handle is closed")
793 getBufferMode other `thenIO_Prim` \ other ->
794 case bufferMode other of
796 writeHandle handle other >>
799 writeHandle handle other >>
802 constructErrorAndFail "hIsNotBuffered"
804 hGetBuffering :: Handle -> IO BufferMode
806 readHandle hndl >>= \ htype ->
808 ErrorHandle ioError ->
809 writeHandle hndl htype >>
812 writeHandle hndl htype >>
813 fail (IllegalOperation "handle is closed")
814 SemiClosedHandle _ _ ->
815 writeHandle hndl htype >>
816 fail (IllegalOperation "handle is closed")
818 getBufferMode other `thenIO_Prim` \ other ->
819 case bufferMode other of
821 writeHandle hndl other >>
824 constructErrorAndFail "hGetBuffering"
826 hIsSeekable :: Handle -> IO Bool
828 readHandle handle >>= \ htype ->
830 ErrorHandle ioError ->
831 writeHandle handle htype >>
834 writeHandle handle htype >>
835 fail (IllegalOperation "handle is closed")
836 SemiClosedHandle _ _ ->
837 writeHandle handle htype >>
838 fail (IllegalOperation "handle is closed")
839 AppendHandle _ _ _ ->
840 writeHandle handle htype >>
843 _ccall_ seekFileP (filePtr other) `thenIO_Prim` \ rc ->
844 writeHandle handle htype >>
848 _ -> constructErrorAndFail "hIsSeekable"
852 %*********************************************************
854 \subsection{Miscellaneous}
856 %*********************************************************
858 These two functions are meant to get things out of @IOErrors@. They don't!
861 ioeGetFileName :: IOError -> Maybe FilePath
862 ioeGetHandle :: IOError -> Maybe Handle
865 ioeGetHandle _ = Nothing -- a stub, essentially
866 ioeGetFileName _ = Nothing -- a stub, essentially