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.
11 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
20 import ArrBase ( ByteArray(..) )
21 import PrelRead ( Read )
27 import Foreign ( ForeignObj, Addr, makeForeignObj, writeForeignObj )
28 import PrelList (span)
29 #if defined(__CONCURRENT_HASKELL__)
35 %*********************************************************
37 \subsection{Types @FilePath@, @Handle@, @Handle__@}
39 %*********************************************************
41 The @Handle@ and @Handle__@ types are defined in @IOBase@.
44 type FilePath = String
46 {-# INLINE newHandle #-}
47 {-# INLINE readHandle #-}
48 {-# INLINE writeHandle #-}
49 newHandle :: Handle__ -> IO Handle
50 readHandle :: Handle -> IO Handle__
51 writeHandle :: Handle -> Handle__ -> IO ()
53 #if defined(__CONCURRENT_HASKELL__)
58 newHandle v = stToIO (newVar v)
59 readHandle h = stToIO (readVar h)
60 writeHandle h v = stToIO (writeVar h v)
65 %*********************************************************
67 \subsection{Functions}
69 %*********************************************************
73 filePtr :: Handle__ -> ForeignObj
75 filePtr :: Handle__ -> Addr
77 filePtr (SemiClosedHandle fp _) = fp
78 filePtr (ReadHandle fp _ _) = fp
79 filePtr (WriteHandle fp _ _) = fp
80 filePtr (AppendHandle fp _ _) = fp
81 filePtr (ReadWriteHandle fp _ _) = fp
83 bufferMode :: Handle__ -> Maybe BufferMode
84 bufferMode (ReadHandle _ m _) = m
85 bufferMode (WriteHandle _ m _) = m
86 bufferMode (AppendHandle _ m _) = m
87 bufferMode (ReadWriteHandle _ m _) = m
89 markHandle :: Handle__ -> Handle__
90 markHandle h@(ReadHandle fp m b)
92 | otherwise = ReadHandle fp m True
93 markHandle h@(WriteHandle fp m b)
95 | otherwise = WriteHandle fp m True
96 markHandle h@(AppendHandle fp m b)
98 | otherwise = AppendHandle fp m True
99 markHandle h@(ReadWriteHandle fp m b)
101 | otherwise = ReadWriteHandle fp m True
104 -------------------------------------------
106 %*********************************************************
108 \subsection[StdHandles]{Standard handles}
110 %*********************************************************
112 Three handles are allocated during program initialisation. The first
113 two manage input or output from the Haskell program's standard input
114 or output channel respectively. The third manages output to the
115 standard error channel. These handles are initially open.
118 stdin, stdout, stderr :: Handle
120 stdin = unsafePerformPrimIO (
121 _ccall_ getLock (``stdin''::Addr) 0 >>= \ rc ->
123 0 -> new_handle ClosedHandle
126 makeForeignObj (``stdin''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
127 new_handle (ReadHandle fp Nothing False)
129 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
145 makeForeignObj (``stdout''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
146 new_handle (WriteHandle fp Nothing False)
148 new_handle (WriteHandle ``stdout'' Nothing False)
150 _ -> constructError "stdout" >>= \ ioError ->
151 new_handle (ErrorHandle ioError)
156 new_handle x = ioToST (newHandle x)
158 stderr = unsafePerformPrimIO (
159 _ccall_ getLock (``stderr''::Addr) 1 >>= \ rc ->
161 0 -> new_handle ClosedHandle
164 makeForeignObj (``stderr''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
165 new_handle (WriteHandle fp (Just NoBuffering) False)
167 new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)
169 _ -> constructError "stderr" >>= \ ioError ->
170 new_handle (ErrorHandle ioError)
175 new_handle x = ioToST (newHandle x)
178 %*********************************************************
180 \subsection[OpeningClosing]{Opening and Closing Files}
182 %*********************************************************
185 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
186 deriving (Eq, Ord, Ix, Enum, Read, Show)
188 openFile :: FilePath -> IOMode -> IO Handle
191 stToIO (_ccall_ openFile f m') >>= \ ptr ->
192 if ptr /= ``NULL'' then
194 makeForeignObj ptr ((``&freeFile'')::Addr) `thenIO_Prim` \ fp ->
195 newHandle (htype fp Nothing False)
197 newHandle (htype ptr Nothing False)
200 stToIO (constructError "openFile") >>= \ ioError@(IOError hn iot msg) ->
202 improved_error -- a HACK, I guess
204 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
205 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
206 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
215 ReadWriteMode -> "r+"
218 ReadMode -> ReadHandle
219 WriteMode -> WriteHandle
220 AppendMode -> AppendHandle
221 ReadWriteMode -> ReadWriteHandle
224 Computation $openFile file mode$ allocates and returns a new, open
225 handle to manage the file {\em file}. It manages input if {\em mode}
226 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
227 and both input and output if mode is $ReadWriteMode$.
229 If the file does not exist and it is opened for output, it should be
230 created as a new file. If {\em mode} is $WriteMode$ and the file
231 already exists, then it should be truncated to zero length. The
232 handle is positioned at the end of the file if {\em mode} is
233 $AppendMode$, and otherwise at the beginning (in which case its
234 internal position is 0).
236 Implementations should enforce, locally to the Haskell process,
237 multiple-reader single-writer locking on files, which is to say that
238 there may either be many handles on the same file which manage input,
239 or just one handle on the file which manages output. If any open or
240 semi-closed handle is managing a file for output, no new handle can be
241 allocated for that file. If any open or semi-closed handle is
242 managing a file for input, new handles can only be allocated if they
243 do not manage output.
245 Two files are the same if they have the same absolute name. An
246 implementation is free to impose stricter conditions.
249 hClose :: Handle -> IO ()
252 readHandle handle >>= \ htype ->
254 ErrorHandle ioError ->
255 writeHandle handle htype >>
258 writeHandle handle htype >>
259 ioe_closedHandle handle
260 SemiClosedHandle fp (buf,_) ->
261 (if buf /= ``NULL'' then
264 returnPrimIO ()) `thenIO_Prim` \ () ->
265 _casm_ `` %r = (char *)%0; '' fp `thenIO_Prim` \ fp_a ->
266 if fp_a /= (``NULL''::Addr) then -- Under what condition can this be NULL?
267 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
268 {- We explicitly close a file object so that we can be told
269 if there were any errors. Note that after @hClose@
270 has been performed, the ForeignObj embedded in the Handle
271 is still lying around in the heap, so care is taken
272 to avoid closing the file object when the ForeignObj
276 -- Mark the foreign object data value as gone to the finaliser (freeFile())
277 writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
279 writeHandle handle ClosedHandle
281 writeHandle handle htype >>
282 constructErrorAndFail "hClose"
285 writeHandle handle htype
287 let fp = filePtr other in
288 _ccall_ closeFile fp `thenIO_Prim` \ rc ->
291 -- Mark the foreign object data
292 writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
294 writeHandle handle ClosedHandle
296 writeHandle handle htype >>
297 constructErrorAndFail "hClose"
300 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
301 computation finishes, any items buffered for output and not already
302 sent to the operating system are flushed as for $flush$.
304 %*********************************************************
306 \subsection[EOF]{Detecting the End of Input}
308 %*********************************************************
311 For a handle {\em hdl} which attached to a physical file, $hFileSize
312 hdl$ returns the size of {\em hdl} in terms of the number of items
313 which can be read from {\em hdl}.
316 hFileSize :: Handle -> IO Integer
318 readHandle handle >>= \ htype ->
320 ErrorHandle ioError ->
321 writeHandle handle htype >>
324 writeHandle handle htype >>
325 ioe_closedHandle handle
326 SemiClosedHandle _ _ ->
327 writeHandle handle htype >>
328 ioe_closedHandle handle
330 -- HACK! We build a unique MP_INT of the right shape to hold
331 -- a single unsigned word, and we let the C routine change the data bits
332 _casm_ ``%r = 1;'' `thenIO_Prim` \ (I# hack#) ->
333 case int2Integer# hack# of
334 result@(J# _ _ d#) ->
336 bogus_bounds = (error "fileSize"::(Int,Int))
338 _ccall_ fileSize (filePtr other) (ByteArray bogus_bounds d#)
339 `thenIO_Prim` \ rc ->
340 writeHandle handle htype >>
344 constructErrorAndFail "hFileSize"
347 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
348 $True$ if no further input can be taken from {\em hdl} or for a
349 physical file, if the current I/O position is equal to the length of
350 the file. Otherwise, it returns $False$.
353 hIsEOF :: Handle -> IO Bool
355 readHandle handle >>= \ htype ->
357 ErrorHandle ioError ->
358 writeHandle handle htype >>
361 writeHandle handle htype >>
362 ioe_closedHandle handle
363 SemiClosedHandle _ _ ->
364 writeHandle handle htype >>
365 ioe_closedHandle handle
367 writeHandle handle htype >>
368 fail (IOError (Just handle) IllegalOperation "handle is not open for reading")
369 AppendHandle _ _ _ ->
370 writeHandle handle htype >>
371 fail (IOError (Just handle) IllegalOperation "handle is not open for reading")
373 _ccall_ fileEOF (filePtr other) `thenIO_Prim` \ rc ->
374 writeHandle handle (markHandle htype) >>
378 _ -> constructErrorAndFail "hIsEOF"
384 %*********************************************************
386 \subsection[Buffering]{Buffering Operations}
388 %*********************************************************
390 Three kinds of buffering are supported: line-buffering,
391 block-buffering or no-buffering. See @IOBase@ for definition
392 and further explanation of what the type represent.
394 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
395 handle {\em hdl} on subsequent reads and writes.
399 If {\em mode} is @LineBuffering@, line-buffering should be
402 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
403 should be enabled if possible. The size of the buffer is {\em n} items
404 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
406 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
409 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
410 to @NoBuffering@, then any items in the output buffer are written to
411 the device, and any items in the input buffer are discarded. The
412 default buffering mode when a handle is opened is
413 implementation-dependent and may depend on the object which is
414 attached to that handle.
417 hSetBuffering :: Handle -> BufferMode -> IO ()
419 hSetBuffering handle mode =
421 (BlockBuffering (Just n))
422 | n <= 0 -> fail (IOError (Just handle) InvalidArgument "illegal buffer size")
424 readHandle handle >>= \ htype ->
425 if isMarked htype then
426 writeHandle handle htype >>
427 fail (IOError (Just handle)
429 "can't set buffering for a dirty handle")
432 ErrorHandle ioError ->
433 writeHandle handle htype >>
436 writeHandle handle htype >>
437 ioe_closedHandle handle
438 SemiClosedHandle _ _ ->
439 writeHandle handle htype >>
440 ioe_closedHandle handle
442 _ccall_ setBuffering (filePtr other) bsize
443 `thenIO_Prim` \ rc ->
445 writeHandle handle ((hcon other) (filePtr other) (Just mode) True)
449 writeHandle handle htype >>
450 constructErrorAndFail "hSetBuffering"
453 isMarked :: Handle__ -> Bool
454 isMarked (ReadHandle fp m b) = b
455 isMarked (WriteHandle fp m b) = b
456 isMarked (AppendHandle fp m b) = b
457 isMarked (ReadWriteHandle fp m b) = b
463 BlockBuffering Nothing -> -2
464 BlockBuffering (Just n) -> n
467 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
469 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
471 hcon (ReadHandle _ _ _) = ReadHandle
472 hcon (WriteHandle _ _ _) = WriteHandle
473 hcon (AppendHandle _ _ _) = AppendHandle
474 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
477 Computation $flush hdl$ causes any items buffered for output in handle
478 {\em hdl} to be sent immediately to the operating system.
481 hFlush :: Handle -> IO ()
483 readHandle handle >>= \ htype ->
485 ErrorHandle ioError ->
486 writeHandle handle htype >>
489 writeHandle handle htype >>
490 ioe_closedHandle handle
491 SemiClosedHandle _ _ ->
492 writeHandle handle htype >>
493 ioe_closedHandle handle
495 _ccall_ flushFile (filePtr other) `thenIO_Prim` \ rc ->
496 writeHandle handle (markHandle htype) >>
500 constructErrorAndFail "hFlush"
504 %*********************************************************
506 \subsection[Seeking]{Repositioning Handles}
508 %*********************************************************
511 data HandlePosn = HandlePosn Handle Int
513 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
514 deriving (Eq, Ord, Ix, Enum, Read, Show)
517 Computation $hGetPosn hdl$ returns the current I/O
518 position of {\em hdl} as an abstract position. Computation
519 $hSetPosn p$ sets the position of {\em hdl}
520 to a previously obtained position {\em p}.
523 hGetPosn :: Handle -> IO HandlePosn
525 readHandle handle >>= \ htype ->
527 ErrorHandle ioError ->
528 writeHandle handle htype >>
531 writeHandle handle htype >>
532 ioe_closedHandle handle
533 SemiClosedHandle _ _ ->
534 writeHandle handle htype >>
535 ioe_closedHandle handle
537 _ccall_ getFilePosn (filePtr other) `thenIO_Prim` \ posn ->
538 writeHandle handle htype >>
540 return (HandlePosn handle posn)
542 constructErrorAndFail "hGetPosn"
544 hSetPosn :: HandlePosn -> IO ()
545 hSetPosn (HandlePosn handle posn) =
546 readHandle handle >>= \ htype ->
548 ErrorHandle ioError ->
549 writeHandle handle htype >>
552 writeHandle handle htype >>
553 ioe_closedHandle handle
554 SemiClosedHandle _ _ ->
555 writeHandle handle htype >>
556 ioe_closedHandle handle
557 AppendHandle _ _ _ ->
558 writeHandle handle htype >>
559 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
561 _ccall_ setFilePosn (filePtr other) posn `thenIO_Prim` \ rc ->
562 writeHandle handle (markHandle htype) >>
566 constructErrorAndFail "hSetPosn"
569 Computation $hSeek hdl mode i$ sets the position of handle
570 {\em hdl} depending on $mode$. If {\em mode} is
572 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
573 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
574 the current position.
575 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
577 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
578 the beginning of the file.
581 Some handles may not be seekable $hIsSeekable$, or only support a
582 subset of the possible positioning operations (e.g. it may only be
583 possible to seek to the end of a tape, or to a positive offset from
584 the beginning or current position).
586 It is not possible to set a negative I/O position, or for a physical
587 file, an I/O position beyond the current end-of-file.
590 hSeek :: Handle -> SeekMode -> Integer -> IO ()
591 hSeek handle mode offset@(J# _ s# d#) =
592 readHandle handle >>= \ htype ->
594 ErrorHandle ioError ->
595 writeHandle handle htype >>
598 writeHandle handle htype >>
599 ioe_closedHandle handle
600 SemiClosedHandle _ _ ->
601 writeHandle handle htype >>
602 ioe_closedHandle handle
603 AppendHandle _ _ _ ->
604 writeHandle handle htype >>
605 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
607 _ccall_ seekFile (filePtr other) whence (I# s#) (ByteArray (0,0) d#)
608 `thenIO_Prim` \ rc ->
609 writeHandle handle (markHandle htype) >>
613 constructErrorAndFail "hSeek"
616 whence = case mode of
617 AbsoluteSeek -> ``SEEK_SET''
618 RelativeSeek -> ``SEEK_CUR''
619 SeekFromEnd -> ``SEEK_END''
622 %*********************************************************
624 \subsection[Query]{Handle Properties}
626 %*********************************************************
628 A number of operations return information about the properties of a
629 handle. Each of these operations returns $True$ if the
630 handle has the specified property, and $False$
633 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
634 {\em hdl} is not block-buffered. Otherwise it returns
635 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
636 $( Just n )$ for block-buffering of {\em n} bytes.
639 hIsOpen :: Handle -> IO Bool
641 readHandle handle >>= \ htype ->
643 ErrorHandle ioError ->
644 writeHandle handle htype >>
647 writeHandle handle htype >>
649 SemiClosedHandle _ _ ->
650 writeHandle handle htype >>
653 writeHandle handle htype >>
656 hIsClosed :: Handle -> IO Bool
658 readHandle handle >>= \ htype ->
660 ErrorHandle ioError ->
661 writeHandle handle htype >>
664 writeHandle handle htype >>
667 writeHandle handle htype >>
670 hIsReadable :: Handle -> IO Bool
672 readHandle handle >>= \ htype ->
674 ErrorHandle ioError ->
675 writeHandle handle htype >>
678 writeHandle handle htype >>
679 ioe_closedHandle handle
680 SemiClosedHandle _ _ ->
681 writeHandle handle htype >>
682 ioe_closedHandle handle
684 writeHandle handle htype >>
685 return (isReadable other)
687 isReadable (ReadHandle _ _ _) = True
688 isReadable (ReadWriteHandle _ _ _) = True
691 hIsWritable :: Handle -> IO Bool
693 readHandle handle >>= \ htype ->
695 ErrorHandle ioError ->
696 writeHandle handle htype >>
699 writeHandle handle htype >>
700 ioe_closedHandle handle
701 SemiClosedHandle _ _ ->
702 writeHandle handle htype >>
703 ioe_closedHandle handle
705 writeHandle handle htype >>
706 return (isWritable other)
708 isWritable (AppendHandle _ _ _) = True
709 isWritable (WriteHandle _ _ _) = True
710 isWritable (ReadWriteHandle _ _ _) = True
713 getBufferMode :: Handle__ -> PrimIO Handle__
714 getBufferMode htype =
715 case bufferMode htype of
716 Just x -> returnPrimIO htype
718 _ccall_ getBufferMode (filePtr htype) `thenPrimIO` \ rc ->
722 0 -> Just NoBuffering
723 -1 -> Just LineBuffering
724 -2 -> Just (BlockBuffering Nothing)
726 n -> Just (BlockBuffering (Just n))
728 returnPrimIO (case htype of
729 ReadHandle fp _ b -> ReadHandle fp mode b
730 WriteHandle fp _ b -> WriteHandle fp mode b
731 AppendHandle fp _ b -> AppendHandle fp mode b
732 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
734 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
735 hIsBlockBuffered handle =
736 readHandle handle >>= \ htype ->
738 ErrorHandle ioError ->
739 writeHandle handle htype >>
742 writeHandle handle htype >>
743 ioe_closedHandle handle
744 SemiClosedHandle _ _ ->
745 writeHandle handle htype >>
746 ioe_closedHandle handle
748 getBufferMode other `thenIO_Prim` \ other ->
749 case bufferMode other of
750 Just (BlockBuffering size) ->
751 writeHandle handle other >>
754 writeHandle handle other >>
755 return (False, Nothing)
757 constructErrorAndFail "hIsBlockBuffered"
759 hIsLineBuffered :: Handle -> IO Bool
760 hIsLineBuffered handle =
761 readHandle handle >>= \ htype ->
763 ErrorHandle ioError ->
764 writeHandle handle htype >>
767 writeHandle handle htype >>
768 ioe_closedHandle handle
769 SemiClosedHandle _ _ ->
770 writeHandle handle htype >>
771 ioe_closedHandle handle
773 getBufferMode other `thenIO_Prim` \ other ->
774 case bufferMode other of
775 Just LineBuffering ->
776 writeHandle handle other >>
779 writeHandle handle other >>
782 constructErrorAndFail "hIsLineBuffered"
784 hIsNotBuffered :: Handle -> IO Bool
785 hIsNotBuffered handle =
786 readHandle handle >>= \ htype ->
788 ErrorHandle ioError ->
789 writeHandle handle htype >>
792 writeHandle handle htype >>
793 ioe_closedHandle handle
794 SemiClosedHandle _ _ ->
795 writeHandle handle htype >>
796 ioe_closedHandle handle
798 getBufferMode other `thenIO_Prim` \ other ->
799 case bufferMode other of
801 writeHandle handle other >>
804 writeHandle handle other >>
807 constructErrorAndFail "hIsNotBuffered"
809 hGetBuffering :: Handle -> IO BufferMode
810 hGetBuffering handle =
811 readHandle handle >>= \ htype ->
813 ErrorHandle ioError ->
814 writeHandle handle htype >>
817 writeHandle handle htype >>
818 ioe_closedHandle handle
819 SemiClosedHandle _ _ ->
820 writeHandle handle htype >>
821 ioe_closedHandle handle
823 getBufferMode other `thenIO_Prim` \ other ->
824 case bufferMode other of
826 writeHandle handle other >>
829 constructErrorAndFail "hGetBuffering"
831 hIsSeekable :: Handle -> IO Bool
833 readHandle handle >>= \ htype ->
835 ErrorHandle ioError ->
836 writeHandle handle htype >>
839 writeHandle handle htype >>
840 ioe_closedHandle handle
841 SemiClosedHandle _ _ ->
842 writeHandle handle htype >>
843 ioe_closedHandle handle
844 AppendHandle _ _ _ ->
845 writeHandle handle htype >>
848 _ccall_ seekFileP (filePtr other) `thenIO_Prim` \ rc ->
849 writeHandle handle htype >>
853 _ -> constructErrorAndFail "hIsSeekable"
857 %*********************************************************
859 \subsection{Miscellaneous}
861 %*********************************************************
863 These two functions are meant to get things out of @IOErrors@. They don't!
866 ioeGetFileName :: IOError -> Maybe FilePath
867 ioeGetErrorString :: IOError -> String
868 ioeGetHandle :: IOError -> Maybe Handle
870 ioeGetHandle (IOError h _ _) = h
871 ioeGetErrorString (IOError _ iot str) =
876 ioeGetFileName (IOError _ _ str) =
877 case span (/=':') str of
883 Internal function for creating an @IOError@ representing the
884 access of a closed file.
888 ioe_closedHandle :: Handle -> IO a
889 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")