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 -#include "cbits/stgio.h" #-}
19 import ArrBase ( ByteArray(..) )
20 import PrelRead ( Read )
26 import Foreign ( makeForeignObj, writeForeignObj )
27 import PrelList (span)
28 #if defined(__CONCURRENT_HASKELL__)
34 %*********************************************************
36 \subsection{Types @FilePath@, @Handle@, @Handle__@}
38 %*********************************************************
40 The @Handle@ and @Handle__@ types are defined in @IOBase@.
43 type FilePath = String
45 {-# INLINE newHandle #-}
46 {-# INLINE readHandle #-}
47 {-# INLINE writeHandle #-}
48 newHandle :: Handle__ -> IO Handle
49 readHandle :: Handle -> IO Handle__
50 writeHandle :: Handle -> Handle__ -> IO ()
52 #if defined(__CONCURRENT_HASKELL__)
57 newHandle v = stToIO (newVar v)
58 readHandle h = stToIO (readVar h)
59 writeHandle h v = stToIO (writeVar h v)
64 %*********************************************************
66 \subsection{Functions}
68 %*********************************************************
72 filePtr :: Handle__ -> ForeignObj
74 filePtr :: Handle__ -> Addr
76 filePtr (SemiClosedHandle fp _) = fp
77 filePtr (ReadHandle fp _ _) = fp
78 filePtr (WriteHandle fp _ _) = fp
79 filePtr (AppendHandle fp _ _) = fp
80 filePtr (ReadWriteHandle fp _ _) = fp
82 bufferMode :: Handle__ -> Maybe BufferMode
83 bufferMode (ReadHandle _ m _) = m
84 bufferMode (WriteHandle _ m _) = m
85 bufferMode (AppendHandle _ m _) = m
86 bufferMode (ReadWriteHandle _ m _) = m
88 markHandle :: Handle__ -> Handle__
89 markHandle h@(ReadHandle fp m b)
91 | otherwise = ReadHandle fp m True
92 markHandle h@(WriteHandle fp m b)
94 | otherwise = WriteHandle fp m True
95 markHandle h@(AppendHandle fp m b)
97 | otherwise = AppendHandle fp m True
98 markHandle h@(ReadWriteHandle fp m b)
100 | otherwise = ReadWriteHandle fp m True
103 -------------------------------------------
105 %*********************************************************
107 \subsection[StdHandles]{Standard handles}
109 %*********************************************************
111 Three handles are allocated during program initialisation. The first
112 two manage input or output from the Haskell program's standard input
113 or output channel respectively. The third manages output to the
114 standard error channel. These handles are initially open.
117 stdin, stdout, stderr :: Handle
119 stdin = unsafePerformPrimIO (
120 _ccall_ getLock (``stdin''::Addr) 0 >>= \ rc ->
122 0 -> new_handle ClosedHandle
125 makeForeignObj (``stdin''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
126 new_handle (ReadHandle fp Nothing False)
128 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
144 makeForeignObj (``stdout''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
145 new_handle (WriteHandle fp Nothing False)
147 new_handle (WriteHandle ``stdout'' Nothing False)
149 _ -> constructError "stdout" >>= \ ioError ->
150 new_handle (ErrorHandle ioError)
155 new_handle x = ioToST (newHandle x)
157 stderr = unsafePerformPrimIO (
158 _ccall_ getLock (``stderr''::Addr) 1 >>= \ rc ->
160 0 -> new_handle ClosedHandle
163 makeForeignObj (``stderr''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
164 new_handle (WriteHandle fp (Just NoBuffering) False)
166 new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)
168 _ -> constructError "stderr" >>= \ ioError ->
169 new_handle (ErrorHandle ioError)
174 new_handle x = ioToST (newHandle x)
177 %*********************************************************
179 \subsection[OpeningClosing]{Opening and Closing Files}
181 %*********************************************************
184 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
185 deriving (Eq, Ord, Ix, Enum, Read, Show)
187 openFile :: FilePath -> IOMode -> IO Handle
190 stToIO (_ccall_ openFile f m') >>= \ ptr ->
191 if ptr /= ``NULL'' then
193 makeForeignObj ptr ((``&freeFile'')::Addr) `thenIO_Prim` \ fp ->
194 newHandle (htype fp Nothing False)
196 newHandle (htype ptr Nothing False)
199 stToIO (constructError "openFile") >>= \ ioError@(IOError hn iot msg) ->
201 improved_error -- a HACK, I guess
203 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
204 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
205 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
214 ReadWriteMode -> "r+"
217 ReadMode -> ReadHandle
218 WriteMode -> WriteHandle
219 AppendMode -> AppendHandle
220 ReadWriteMode -> ReadWriteHandle
223 Computation $openFile file mode$ allocates and returns a new, open
224 handle to manage the file {\em file}. It manages input if {\em mode}
225 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
226 and both input and output if mode is $ReadWriteMode$.
228 If the file does not exist and it is opened for output, it should be
229 created as a new file. If {\em mode} is $WriteMode$ and the file
230 already exists, then it should be truncated to zero length. The
231 handle is positioned at the end of the file if {\em mode} is
232 $AppendMode$, and otherwise at the beginning (in which case its
233 internal position is 0).
235 Implementations should enforce, locally to the Haskell process,
236 multiple-reader single-writer locking on files, which is to say that
237 there may either be many handles on the same file which manage input,
238 or just one handle on the file which manages output. If any open or
239 semi-closed handle is managing a file for output, no new handle can be
240 allocated for that file. If any open or semi-closed handle is
241 managing a file for input, new handles can only be allocated if they
242 do not manage output.
244 Two files are the same if they have the same absolute name. An
245 implementation is free to impose stricter conditions.
248 hClose :: Handle -> IO ()
251 readHandle handle >>= \ htype ->
253 ErrorHandle ioError ->
254 writeHandle handle htype >>
257 writeHandle handle htype >>
258 ioe_closedHandle handle
259 SemiClosedHandle fp (buf,_) ->
260 (if buf /= ``NULL'' then
263 returnPrimIO ()) `thenIO_Prim` \ () ->
264 _casm_ `` %r = (char *)%0; '' fp `thenIO_Prim` \ fp_a ->
265 if fp_a /= (``NULL''::Addr) then -- Under what condition can this be NULL?
266 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
267 {- We explicitly close a file object so that we can be told
268 if there were any errors. Note that after @hClose@
269 has been performed, the ForeignObj embedded in the Handle
270 is still lying around in the heap, so care is taken
271 to avoid closing the file object when the ForeignObj
275 -- Mark the foreign object data value as gone to the finaliser (freeFile())
276 writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
278 writeHandle handle ClosedHandle
280 writeHandle handle htype >>
281 constructErrorAndFail "hClose"
284 writeHandle handle htype
286 let fp = filePtr other in
287 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
290 -- Mark the foreign object data
291 writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
293 writeHandle handle ClosedHandle
295 writeHandle handle htype >>
296 constructErrorAndFail "hClose"
299 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
300 computation finishes, any items buffered for output and not already
301 sent to the operating system are flushed as for $flush$.
303 %*********************************************************
305 \subsection[EOF]{Detecting the End of Input}
307 %*********************************************************
310 For a handle {\em hdl} which attached to a physical file, $hFileSize
311 hdl$ returns the size of {\em hdl} in terms of the number of items
312 which can be read from {\em hdl}.
315 hFileSize :: Handle -> IO Integer
317 readHandle handle >>= \ htype ->
319 ErrorHandle ioError ->
320 writeHandle handle htype >>
323 writeHandle handle htype >>
324 ioe_closedHandle handle
325 SemiClosedHandle _ _ ->
326 writeHandle handle htype >>
327 ioe_closedHandle handle
329 -- HACK! We build a unique MP_INT of the right shape to hold
330 -- a single unsigned word, and we let the C routine change the data bits
331 _casm_ ``%r = 1;'' `thenIO_Prim` \ (I# hack#) ->
332 case int2Integer# hack# of
333 result@(J# _ _ d#) ->
335 bogus_bounds = (error "fileSize"::(Int,Int))
337 _ccall_ fileSize (filePtr other) (ByteArray bogus_bounds d#)
338 `thenIO_Prim` \ rc ->
339 writeHandle handle htype >>
343 constructErrorAndFail "hFileSize"
346 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
347 $True$ if no further input can be taken from {\em hdl} or for a
348 physical file, if the current I/O position is equal to the length of
349 the file. Otherwise, it returns $False$.
352 hIsEOF :: Handle -> IO Bool
354 readHandle handle >>= \ htype ->
356 ErrorHandle ioError ->
357 writeHandle handle htype >>
360 writeHandle handle htype >>
361 ioe_closedHandle handle
362 SemiClosedHandle _ _ ->
363 writeHandle handle htype >>
364 ioe_closedHandle handle
366 writeHandle handle htype >>
367 fail (IOError (Just handle) IllegalOperation "handle is not open for reading")
368 AppendHandle _ _ _ ->
369 writeHandle handle htype >>
370 fail (IOError (Just handle) IllegalOperation "handle is not open for reading")
372 _ccall_ fileEOF (filePtr other) `thenIO_Prim` \ rc ->
373 writeHandle handle (markHandle htype) >>
377 _ -> constructErrorAndFail "hIsEOF"
383 %*********************************************************
385 \subsection[Buffering]{Buffering Operations}
387 %*********************************************************
389 Three kinds of buffering are supported: line-buffering,
390 block-buffering or no-buffering. See @IOBase@ for definition
391 and further explanation of what the type represent.
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 (IOError (Just handle) InvalidArgument "illegal buffer size")
423 readHandle handle >>= \ htype ->
424 if isMarked htype then
425 writeHandle handle htype >>
426 fail (IOError (Just handle)
428 "can't set buffering for a dirty handle")
431 ErrorHandle ioError ->
432 writeHandle handle htype >>
435 writeHandle handle htype >>
436 ioe_closedHandle handle
437 SemiClosedHandle _ _ ->
438 writeHandle handle htype >>
439 ioe_closedHandle handle
441 _ccall_ setBuffering (filePtr other) bsize
442 `thenIO_Prim` \ rc ->
444 writeHandle handle ((hcon other) (filePtr other) (Just mode) True)
448 writeHandle handle htype >>
449 constructErrorAndFail "hSetBuffering"
452 isMarked :: Handle__ -> Bool
453 isMarked (ReadHandle fp m b) = b
454 isMarked (WriteHandle fp m b) = b
455 isMarked (AppendHandle fp m b) = b
456 isMarked (ReadWriteHandle fp m b) = b
462 BlockBuffering Nothing -> -2
463 BlockBuffering (Just n) -> n
466 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
468 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
470 hcon (ReadHandle _ _ _) = ReadHandle
471 hcon (WriteHandle _ _ _) = WriteHandle
472 hcon (AppendHandle _ _ _) = AppendHandle
473 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
476 Computation $flush hdl$ causes any items buffered for output in handle
477 {\em hdl} to be sent immediately to the operating system.
480 hFlush :: Handle -> IO ()
482 readHandle handle >>= \ htype ->
484 ErrorHandle ioError ->
485 writeHandle handle htype >>
488 writeHandle handle htype >>
489 ioe_closedHandle handle
490 SemiClosedHandle _ _ ->
491 writeHandle handle htype >>
492 ioe_closedHandle handle
494 _ccall_ flushFile (filePtr other) `thenIO_Prim` \ rc ->
495 writeHandle handle (markHandle htype) >>
499 constructErrorAndFail "hFlush"
503 %*********************************************************
505 \subsection[Seeking]{Repositioning Handles}
507 %*********************************************************
510 data HandlePosn = HandlePosn Handle Int
512 instance Eq HandlePosn{-partain-}
514 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
515 deriving (Eq, Ord, Ix, Enum, Read, Show)
518 Computation $hGetPosn hdl$ returns the current I/O
519 position of {\em hdl} as an abstract position. Computation
520 $hSetPosn p$ sets the position of {\em hdl}
521 to a previously obtained position {\em p}.
524 hGetPosn :: Handle -> IO HandlePosn
526 readHandle handle >>= \ htype ->
528 ErrorHandle ioError ->
529 writeHandle handle htype >>
532 writeHandle handle htype >>
533 ioe_closedHandle handle
534 SemiClosedHandle _ _ ->
535 writeHandle handle htype >>
536 ioe_closedHandle handle
538 _ccall_ getFilePosn (filePtr other) `thenIO_Prim` \ posn ->
539 writeHandle handle htype >>
541 return (HandlePosn handle posn)
543 constructErrorAndFail "hGetPosn"
545 hSetPosn :: HandlePosn -> IO ()
546 hSetPosn (HandlePosn handle posn) =
547 readHandle handle >>= \ htype ->
549 ErrorHandle ioError ->
550 writeHandle handle htype >>
553 writeHandle handle htype >>
554 ioe_closedHandle handle
555 SemiClosedHandle _ _ ->
556 writeHandle handle htype >>
557 ioe_closedHandle handle
558 AppendHandle _ _ _ ->
559 writeHandle handle htype >>
560 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
562 _ccall_ setFilePosn (filePtr other) posn `thenIO_Prim` \ rc ->
563 writeHandle handle (markHandle htype) >>
567 constructErrorAndFail "hSetPosn"
570 Computation $hSeek hdl mode i$ sets the position of handle
571 {\em hdl} depending on $mode$. If {\em mode} is
573 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
574 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
575 the current position.
576 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
578 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
579 the beginning of the file.
582 Some handles may not be seekable $hIsSeekable$, or only support a
583 subset of the possible positioning operations (e.g. it may only be
584 possible to seek to the end of a tape, or to a positive offset from
585 the beginning or current position).
587 It is not possible to set a negative I/O position, or for a physical
588 file, an I/O position beyond the current end-of-file.
591 hSeek :: Handle -> SeekMode -> Integer -> IO ()
592 hSeek handle mode offset@(J# _ s# d#) =
593 readHandle handle >>= \ htype ->
595 ErrorHandle ioError ->
596 writeHandle handle htype >>
599 writeHandle handle htype >>
600 ioe_closedHandle handle
601 SemiClosedHandle _ _ ->
602 writeHandle handle htype >>
603 ioe_closedHandle handle
604 AppendHandle _ _ _ ->
605 writeHandle handle htype >>
606 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
608 _ccall_ seekFile (filePtr other) whence (I# s#) (ByteArray (0,0) d#)
609 `thenIO_Prim` \ rc ->
610 writeHandle handle (markHandle htype) >>
614 constructErrorAndFail "hSeek"
617 whence = case mode of
618 AbsoluteSeek -> ``SEEK_SET''
619 RelativeSeek -> ``SEEK_CUR''
620 SeekFromEnd -> ``SEEK_END''
623 %*********************************************************
625 \subsection[Query]{Handle Properties}
627 %*********************************************************
629 A number of operations return information about the properties of a
630 handle. Each of these operations returns $True$ if the
631 handle has the specified property, and $False$
634 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
635 {\em hdl} is not block-buffered. Otherwise it returns
636 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
637 $( Just n )$ for block-buffering of {\em n} bytes.
640 hIsOpen :: Handle -> IO Bool
642 readHandle handle >>= \ htype ->
644 ErrorHandle ioError ->
645 writeHandle handle htype >>
648 writeHandle handle htype >>
650 SemiClosedHandle _ _ ->
651 writeHandle handle htype >>
654 writeHandle handle htype >>
657 hIsClosed :: Handle -> IO Bool
659 readHandle handle >>= \ htype ->
661 ErrorHandle ioError ->
662 writeHandle handle htype >>
665 writeHandle handle htype >>
668 writeHandle handle htype >>
671 hIsReadable :: Handle -> IO Bool
673 readHandle handle >>= \ htype ->
675 ErrorHandle ioError ->
676 writeHandle handle htype >>
679 writeHandle handle htype >>
680 ioe_closedHandle handle
681 SemiClosedHandle _ _ ->
682 writeHandle handle htype >>
683 ioe_closedHandle handle
685 writeHandle handle htype >>
686 return (isReadable other)
688 isReadable (ReadHandle _ _ _) = True
689 isReadable (ReadWriteHandle _ _ _) = True
692 hIsWritable :: Handle -> IO Bool
694 readHandle handle >>= \ htype ->
696 ErrorHandle ioError ->
697 writeHandle handle htype >>
700 writeHandle handle htype >>
701 ioe_closedHandle handle
702 SemiClosedHandle _ _ ->
703 writeHandle handle htype >>
704 ioe_closedHandle handle
706 writeHandle handle htype >>
707 return (isWritable other)
709 isWritable (AppendHandle _ _ _) = True
710 isWritable (WriteHandle _ _ _) = True
711 isWritable (ReadWriteHandle _ _ _) = True
714 getBufferMode :: Handle__ -> PrimIO Handle__
715 getBufferMode htype =
716 case bufferMode htype of
717 Just x -> returnPrimIO htype
719 _ccall_ getBufferMode (filePtr htype) `thenPrimIO` \ rc ->
723 0 -> Just NoBuffering
724 -1 -> Just LineBuffering
725 -2 -> Just (BlockBuffering Nothing)
727 n -> Just (BlockBuffering (Just n))
729 returnPrimIO (case htype of
730 ReadHandle fp _ b -> ReadHandle fp mode b
731 WriteHandle fp _ b -> WriteHandle fp mode b
732 AppendHandle fp _ b -> AppendHandle fp mode b
733 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
735 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
736 hIsBlockBuffered handle =
737 readHandle handle >>= \ htype ->
739 ErrorHandle ioError ->
740 writeHandle handle htype >>
743 writeHandle handle htype >>
744 ioe_closedHandle handle
745 SemiClosedHandle _ _ ->
746 writeHandle handle htype >>
747 ioe_closedHandle handle
749 getBufferMode other `thenIO_Prim` \ other ->
750 case bufferMode other of
751 Just (BlockBuffering size) ->
752 writeHandle handle other >>
755 writeHandle handle other >>
756 return (False, Nothing)
758 constructErrorAndFail "hIsBlockBuffered"
760 hIsLineBuffered :: Handle -> IO Bool
761 hIsLineBuffered handle =
762 readHandle handle >>= \ htype ->
764 ErrorHandle ioError ->
765 writeHandle handle htype >>
768 writeHandle handle htype >>
769 ioe_closedHandle handle
770 SemiClosedHandle _ _ ->
771 writeHandle handle htype >>
772 ioe_closedHandle handle
774 getBufferMode other `thenIO_Prim` \ other ->
775 case bufferMode other of
776 Just LineBuffering ->
777 writeHandle handle other >>
780 writeHandle handle other >>
783 constructErrorAndFail "hIsLineBuffered"
785 hIsNotBuffered :: Handle -> IO Bool
786 hIsNotBuffered handle =
787 readHandle handle >>= \ htype ->
789 ErrorHandle ioError ->
790 writeHandle handle htype >>
793 writeHandle handle htype >>
794 ioe_closedHandle handle
795 SemiClosedHandle _ _ ->
796 writeHandle handle htype >>
797 ioe_closedHandle handle
799 getBufferMode other `thenIO_Prim` \ other ->
800 case bufferMode other of
802 writeHandle handle other >>
805 writeHandle handle other >>
808 constructErrorAndFail "hIsNotBuffered"
810 hGetBuffering :: Handle -> IO BufferMode
811 hGetBuffering handle =
812 readHandle handle >>= \ htype ->
814 ErrorHandle ioError ->
815 writeHandle handle htype >>
818 writeHandle handle htype >>
819 ioe_closedHandle handle
820 SemiClosedHandle _ _ ->
821 writeHandle handle htype >>
822 ioe_closedHandle handle
824 getBufferMode other `thenIO_Prim` \ other ->
825 case bufferMode other of
827 writeHandle handle other >>
830 constructErrorAndFail "hGetBuffering"
832 hIsSeekable :: Handle -> IO Bool
834 readHandle handle >>= \ htype ->
836 ErrorHandle ioError ->
837 writeHandle handle htype >>
840 writeHandle handle htype >>
841 ioe_closedHandle handle
842 SemiClosedHandle _ _ ->
843 writeHandle handle htype >>
844 ioe_closedHandle handle
845 AppendHandle _ _ _ ->
846 writeHandle handle htype >>
849 _ccall_ seekFileP (filePtr other) `thenIO_Prim` \ rc ->
850 writeHandle handle htype >>
854 _ -> constructErrorAndFail "hIsSeekable"
858 %*********************************************************
860 \subsection{Miscellaneous}
862 %*********************************************************
864 These two functions are meant to get things out of @IOErrors@. They don't!
867 ioeGetFileName :: IOError -> Maybe FilePath
868 ioeGetErrorString :: IOError -> String
869 ioeGetHandle :: IOError -> Maybe Handle
871 ioeGetHandle (IOError h _ _) = h
872 ioeGetErrorString (IOError _ iot str) =
877 ioeGetFileName (IOError _ _ str) =
878 case span (/=':') str of
884 Internal function for creating an @IOError@ representing the
885 access of a closed file.
889 ioe_closedHandle :: Handle -> IO a
890 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")