2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[PrelHandle]{Module @PrelHandle@}
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" #-}
15 module PrelHandle where
18 import PrelArr ( ByteArray(..), newVar, readVar, writeVar )
19 import PrelRead ( Read )
20 import PrelList ( span )
22 import PrelUnsafe ( unsafePerformIO )
27 import PrelErr ( error )
31 #ifndef __PARALLEL_HASKELL__
32 import PrelForeign ( ForeignObj, makeForeignObj, writeForeignObj )
35 import PrelConc -- concurrent only
39 %*********************************************************
41 \subsection{Types @FilePath@, @Handle@, @Handle__@}
43 %*********************************************************
45 The @Handle@ and @Handle__@ types are defined in @IOBase@.
48 type FilePath = String
50 {-# INLINE newHandle #-}
51 {-# INLINE readHandle #-}
52 {-# INLINE writeHandle #-}
53 newHandle :: Handle__ -> IO Handle
54 readHandle :: Handle -> IO Handle__
55 writeHandle :: Handle -> Handle__ -> IO ()
57 #if defined(__CONCURRENT_HASKELL__)
59 -- Use MVars for concurrent Haskell
60 newHandle hc = newMVar hc >>= \ h ->
63 readHandle (Handle h) = takeMVar h
64 writeHandle (Handle h) hc = putMVar h hc
68 -- Use ordinary MutableVars for non-concurrent Haskell
69 newHandle hc = stToIO (newVar hc >>= \ h ->
72 readHandle (Handle h) = stToIO (readVar h)
73 writeHandle (Handle h) hc = stToIO (writeVar h hc)
78 %*********************************************************
80 \subsection{Functions}
82 %*********************************************************
85 #ifndef __PARALLEL_HASKELL__
86 filePtr :: Handle__ -> ForeignObj
88 filePtr :: Handle__ -> Addr
90 filePtr (SemiClosedHandle fp _) = fp
91 filePtr (ReadHandle fp _ _) = fp
92 filePtr (WriteHandle fp _ _) = fp
93 filePtr (AppendHandle fp _ _) = fp
94 filePtr (ReadWriteHandle fp _ _) = fp
96 bufferMode :: Handle__ -> Maybe BufferMode
97 bufferMode (ReadHandle _ m _) = m
98 bufferMode (WriteHandle _ m _) = m
99 bufferMode (AppendHandle _ m _) = m
100 bufferMode (ReadWriteHandle _ m _) = m
102 markHandle :: Handle__ -> Handle__
103 markHandle h@(ReadHandle fp m b)
105 | otherwise = ReadHandle fp m True
106 markHandle h@(WriteHandle fp m b)
108 | otherwise = WriteHandle fp m True
109 markHandle h@(AppendHandle fp m b)
111 | otherwise = AppendHandle fp m True
112 markHandle h@(ReadWriteHandle fp m b)
114 | otherwise = ReadWriteHandle fp m True
117 -------------------------------------------
119 %*********************************************************
121 \subsection[StdHandles]{Standard handles}
123 %*********************************************************
125 Three handles are allocated during program initialisation. The first
126 two manage input or output from the Haskell program's standard input
127 or output channel respectively. The third manages output to the
128 standard error channel. These handles are initially open.
131 stdin, stdout, stderr :: Handle
133 stdin = unsafePerformIO (do
134 rc <- _ccall_ getLock (``stdin''::Addr) 0
136 0 -> newHandle ClosedHandle
138 #ifndef __PARALLEL_HASKELL__
139 fp <- makeForeignObj (``stdin''::Addr) (``&freeStdFile''::Addr)
140 newHandle (ReadHandle fp Nothing False)
142 newHandle (ReadHandle ``stdin'' Nothing False)
144 _ -> do ioError <- constructError "stdin"
145 newHandle (ErrorHandle ioError)
148 stdout = unsafePerformIO (do
149 rc <- _ccall_ getLock (``stdout''::Addr) 1
151 0 -> newHandle ClosedHandle
153 #ifndef __PARALLEL_HASKELL__
154 fp <- makeForeignObj (``stdout''::Addr) (``&freeStdFile''::Addr)
155 newHandle (WriteHandle fp Nothing False)
157 newHandle (WriteHandle ``stdout'' Nothing False)
159 _ -> do ioError <- constructError "stdout"
160 newHandle (ErrorHandle ioError)
163 stderr = unsafePerformIO (do
164 rc <- _ccall_ getLock (``stderr''::Addr) 1
166 0 -> newHandle ClosedHandle
168 #ifndef __PARALLEL_HASKELL__
169 fp <- makeForeignObj (``stderr''::Addr) (``&freeStdFile''::Addr)
170 newHandle (WriteHandle fp (Just NoBuffering) False)
172 newHandle (WriteHandle ``stderr'' (Just NoBuffering) False)
174 _ -> do ioError <- constructError "stderr"
175 newHandle (ErrorHandle ioError)
179 %*********************************************************
181 \subsection[OpeningClosing]{Opening and Closing Files}
183 %*********************************************************
186 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
187 deriving (Eq, Ord, Ix, Enum, Read, Show)
192 deriving (Eq, Read, Show)
194 openFile :: FilePath -> IOMode -> IO Handle
195 openFile fp im = openFileEx fp (TextMode im)
197 openFileEx :: FilePath -> IOModeEx -> IO Handle
200 ptr <- _ccall_ openFile f m'
201 if ptr /= ``NULL'' then do
202 #ifndef __PARALLEL_HASKELL__
203 fp <- makeForeignObj ptr ((``&freeFile'')::Addr)
204 newHandle (htype fp Nothing False)
206 newHandle (htype ptr Nothing False)
209 ioError@(IOError hn iot msg) <- constructError "openFile"
211 improved_error -- a HACK, I guess
213 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
214 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
215 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
220 BinaryMode imo -> imo
224 BinaryMode _ -> imo' ++ "b"
232 ReadWriteMode -> "r+"
235 ReadMode -> ReadHandle
236 WriteMode -> WriteHandle
237 AppendMode -> AppendHandle
238 ReadWriteMode -> ReadWriteHandle
241 Computation $openFile file mode$ allocates and returns a new, open
242 handle to manage the file {\em file}. It manages input if {\em mode}
243 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
244 and both input and output if mode is $ReadWriteMode$.
246 If the file does not exist and it is opened for output, it should be
247 created as a new file. If {\em mode} is $WriteMode$ and the file
248 already exists, then it should be truncated to zero length. The
249 handle is positioned at the end of the file if {\em mode} is
250 $AppendMode$, and otherwise at the beginning (in which case its
251 internal position is 0).
253 Implementations should enforce, locally to the Haskell process,
254 multiple-reader single-writer locking on files, which is to say that
255 there may either be many handles on the same file which manage input,
256 or just one handle on the file which manages output. If any open or
257 semi-closed handle is managing a file for output, no new handle can be
258 allocated for that file. If any open or semi-closed handle is
259 managing a file for input, new handles can only be allocated if they
260 do not manage output.
262 Two files are the same if they have the same absolute name. An
263 implementation is free to impose stricter conditions.
266 hClose :: Handle -> IO ()
269 htype <- readHandle handle
271 ErrorHandle ioError -> do
272 writeHandle handle htype
275 writeHandle handle htype
276 ioe_closedHandle handle
277 SemiClosedHandle fp (buf,_) -> do
278 (if buf /= ``NULL'' then
282 fp_a <- _casm_ `` %r = (char *)%0; '' fp
283 if fp_a /= (``NULL''::Addr) then do
284 -- Under what condition can this be NULL?
285 rc <- _ccall_ closeFile fp
286 {- We explicitly close a file object so that we can be told
287 if there were any errors. Note that after @hClose@
288 has been performed, the ForeignObj embedded in the Handle
289 is still lying around in the heap, so care is taken
290 to avoid closing the file object when the ForeignObj
293 #ifndef __PARALLEL_HASKELL__
294 -- Mark the foreign object data value as
295 -- gone to the finaliser (freeFile())
296 writeForeignObj fp ``NULL''
298 writeHandle handle ClosedHandle
300 writeHandle handle htype
301 constructErrorAndFail "hClose"
303 else writeHandle handle htype
306 let fp = filePtr other
307 rc <- _ccall_ closeFile fp
309 #ifndef __PARALLEL_HASKELL__
310 -- Mark the foreign object data
311 writeForeignObj fp ``NULL''
313 writeHandle handle ClosedHandle
315 writeHandle handle htype
316 constructErrorAndFail "hClose"
319 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
320 computation finishes, any items buffered for output and not already
321 sent to the operating system are flushed as for $flush$.
323 %*********************************************************
325 \subsection[EOF]{Detecting the End of Input}
327 %*********************************************************
330 For a handle {\em hdl} which attached to a physical file, $hFileSize
331 hdl$ returns the size of {\em hdl} in terms of the number of items
332 which can be read from {\em hdl}.
335 hFileSize :: Handle -> IO Integer
336 hFileSize handle = do
337 htype <- readHandle handle
339 ErrorHandle ioError -> do
340 writeHandle handle htype
343 writeHandle handle htype
344 ioe_closedHandle handle
345 SemiClosedHandle _ _ -> do
346 writeHandle handle htype
347 ioe_closedHandle handle
349 -- HACK! We build a unique MP_INT of the right shape to hold
350 -- a single unsigned word, and we let the C routine
351 -- change the data bits
353 -- For some reason, this fails to typecheck if converted to a do
355 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
356 case int2Integer# hack# of
357 result@(J# _ _ d#) -> do
358 let bogus_bounds = (error "fileSize"::(Int,Int))
359 rc <- _ccall_ fileSize (filePtr other)
360 (ByteArray bogus_bounds d#)
361 writeHandle handle htype
365 constructErrorAndFail "hFileSize"
368 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
369 $True$ if no further input can be taken from {\em hdl} or for a
370 physical file, if the current I/O position is equal to the length of
371 the file. Otherwise, it returns $False$.
374 hIsEOF :: Handle -> IO Bool
376 htype <- readHandle handle
378 ErrorHandle ioError -> do
379 writeHandle handle htype
382 writeHandle handle htype
383 ioe_closedHandle handle
384 SemiClosedHandle _ _ -> do
385 writeHandle handle htype
386 ioe_closedHandle handle
387 WriteHandle _ _ _ -> do
388 writeHandle handle htype
389 fail (IOError (Just handle) IllegalOperation
390 "handle is not open for reading")
391 AppendHandle _ _ _ -> do
392 writeHandle handle htype
393 fail (IOError (Just handle) IllegalOperation
394 "handle is not open for reading")
396 rc <- _ccall_ fileEOF (filePtr other)
397 writeHandle handle (markHandle htype)
401 _ -> constructErrorAndFail "hIsEOF"
407 %*********************************************************
409 \subsection[Buffering]{Buffering Operations}
411 %*********************************************************
413 Three kinds of buffering are supported: line-buffering,
414 block-buffering or no-buffering. See @IOBase@ for definition
415 and further explanation of what the type represent.
417 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
418 handle {\em hdl} on subsequent reads and writes.
422 If {\em mode} is @LineBuffering@, line-buffering should be
425 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
426 should be enabled if possible. The size of the buffer is {\em n} items
427 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
429 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
432 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
433 to @NoBuffering@, then any items in the output buffer are written to
434 the device, and any items in the input buffer are discarded. The
435 default buffering mode when a handle is opened is
436 implementation-dependent and may depend on the object which is
437 attached to that handle.
440 hSetBuffering :: Handle -> BufferMode -> IO ()
442 hSetBuffering handle mode =
444 BlockBuffering (Just n)
445 | n <= 0 -> fail (IOError (Just handle) InvalidArgument
446 "illegal buffer size")
448 htype <- readHandle handle
449 if isMarked htype then do
450 writeHandle handle htype
451 fail (IOError (Just handle)
453 "can't set buffering for a dirty handle")
456 ErrorHandle ioError -> do
457 writeHandle handle htype
460 writeHandle handle htype
461 ioe_closedHandle handle
462 SemiClosedHandle _ _ -> do
463 writeHandle handle htype
464 ioe_closedHandle handle
466 rc <- _ccall_ setBuffering (filePtr other) bsize
468 writeHandle handle ((hcon other) (filePtr other)
471 writeHandle handle htype
472 constructErrorAndFail "hSetBuffering"
475 isMarked :: Handle__ -> Bool
476 isMarked (ReadHandle fp m b) = b
477 isMarked (WriteHandle fp m b) = b
478 isMarked (AppendHandle fp m b) = b
479 isMarked (ReadWriteHandle fp m b) = b
486 BlockBuffering Nothing -> -2
487 BlockBuffering (Just n) -> n
489 #ifndef __PARALLEL_HASKELL__
490 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
492 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
494 hcon (ReadHandle _ _ _) = ReadHandle
495 hcon (WriteHandle _ _ _) = WriteHandle
496 hcon (AppendHandle _ _ _) = AppendHandle
497 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
500 Computation $flush hdl$ causes any items buffered for output in handle
501 {\em hdl} to be sent immediately to the operating system.
504 hFlush :: Handle -> IO ()
506 htype <- readHandle handle
508 ErrorHandle ioError -> do
509 writeHandle handle htype
512 writeHandle handle htype
513 ioe_closedHandle handle
514 SemiClosedHandle _ _ -> do
515 writeHandle handle htype
516 ioe_closedHandle handle
518 rc <- _ccall_ flushFile (filePtr other)
519 writeHandle handle (markHandle htype)
523 constructErrorAndFail "hFlush"
527 %*********************************************************
529 \subsection[Seeking]{Repositioning Handles}
531 %*********************************************************
534 data HandlePosn = HandlePosn Handle Int
536 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
537 deriving (Eq, Ord, Ix, Enum, Read, Show)
540 Computation $hGetPosn hdl$ returns the current I/O
541 position of {\em hdl} as an abstract position. Computation
542 $hSetPosn p$ sets the position of {\em hdl}
543 to a previously obtained position {\em p}.
546 hGetPosn :: Handle -> IO HandlePosn
548 htype <- readHandle handle
550 ErrorHandle ioError -> do
551 writeHandle handle htype
554 writeHandle handle htype
555 ioe_closedHandle handle
556 SemiClosedHandle _ _ -> do
557 writeHandle handle htype
558 ioe_closedHandle handle
560 posn <- _ccall_ getFilePosn (filePtr other)
561 writeHandle handle htype
563 return (HandlePosn handle posn)
565 constructErrorAndFail "hGetPosn"
567 hSetPosn :: HandlePosn -> IO ()
568 hSetPosn (HandlePosn handle posn) = do
569 htype <- readHandle handle
571 ErrorHandle ioError -> do
572 writeHandle handle htype
575 writeHandle handle htype
576 ioe_closedHandle handle
577 SemiClosedHandle _ _ -> do
578 writeHandle handle htype
579 ioe_closedHandle handle
580 AppendHandle _ _ _ -> do
581 writeHandle handle htype
582 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
584 rc <- _ccall_ setFilePosn (filePtr other) posn
585 writeHandle handle (markHandle htype)
589 constructErrorAndFail "hSetPosn"
592 Computation $hSeek hdl mode i$ sets the position of handle
593 {\em hdl} depending on $mode$. If {\em mode} is
595 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
596 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
597 the current position.
598 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
600 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
601 the beginning of the file.
604 Some handles may not be seekable $hIsSeekable$, or only support a
605 subset of the possible positioning operations (e.g. it may only be
606 possible to seek to the end of a tape, or to a positive offset from
607 the beginning or current position).
609 It is not possible to set a negative I/O position, or for a physical
610 file, an I/O position beyond the current end-of-file.
613 hSeek :: Handle -> SeekMode -> Integer -> IO ()
614 hSeek handle mode offset@(J# _ s# d#) = do
615 htype <- readHandle handle
617 ErrorHandle ioError -> do
618 writeHandle handle htype
621 writeHandle handle htype
622 ioe_closedHandle handle
623 SemiClosedHandle _ _ -> do
624 writeHandle handle htype
625 ioe_closedHandle handle
626 AppendHandle _ _ _ -> do
627 writeHandle handle htype
628 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
630 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
632 writeHandle handle (markHandle htype)
636 constructErrorAndFail "hSeek"
639 whence = case mode of
640 AbsoluteSeek -> ``SEEK_SET''
641 RelativeSeek -> ``SEEK_CUR''
642 SeekFromEnd -> ``SEEK_END''
645 %*********************************************************
647 \subsection[Query]{Handle Properties}
649 %*********************************************************
651 A number of operations return information about the properties of a
652 handle. Each of these operations returns $True$ if the
653 handle has the specified property, and $False$
656 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
657 {\em hdl} is not block-buffered. Otherwise it returns
658 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
659 $( Just n )$ for block-buffering of {\em n} bytes.
662 hIsOpen :: Handle -> IO Bool
664 htype <- readHandle handle
666 ErrorHandle ioError -> do
667 writeHandle handle htype
670 writeHandle handle htype
672 SemiClosedHandle _ _ -> do
673 writeHandle handle htype
676 writeHandle handle htype
679 hIsClosed :: Handle -> IO Bool
680 hIsClosed handle = do
681 htype <- readHandle handle
683 ErrorHandle ioError -> do
684 writeHandle handle htype
687 writeHandle handle htype
690 writeHandle handle htype
693 hIsReadable :: Handle -> IO Bool
694 hIsReadable handle = do
695 htype <- readHandle handle
697 ErrorHandle ioError -> do
698 writeHandle handle htype
701 writeHandle handle htype
702 ioe_closedHandle handle
703 SemiClosedHandle _ _ -> do
704 writeHandle handle htype
705 ioe_closedHandle handle
707 writeHandle handle htype
708 return (isReadable other)
710 isReadable (ReadHandle _ _ _) = True
711 isReadable (ReadWriteHandle _ _ _) = True
714 hIsWritable :: Handle -> IO Bool
715 hIsWritable handle = do
716 htype <- readHandle handle
718 ErrorHandle ioError -> do
719 writeHandle handle htype
722 writeHandle handle htype
723 ioe_closedHandle handle
724 SemiClosedHandle _ _ -> do
725 writeHandle handle htype
726 ioe_closedHandle handle
728 writeHandle handle htype
729 return (isWritable other)
731 isWritable (AppendHandle _ _ _) = True
732 isWritable (WriteHandle _ _ _) = True
733 isWritable (ReadWriteHandle _ _ _) = True
736 getBufferMode :: Handle__ -> IO Handle__
737 getBufferMode htype =
738 case bufferMode htype of
739 Just x -> return htype
741 rc <- _ccall_ getBufferMode (filePtr htype)
745 0 -> Just NoBuffering
746 -1 -> Just LineBuffering
747 -2 -> Just (BlockBuffering Nothing)
749 n -> Just (BlockBuffering (Just n))
750 return (case htype of
751 ReadHandle fp _ b -> ReadHandle fp mode b
752 WriteHandle fp _ b -> WriteHandle fp mode b
753 AppendHandle fp _ b -> AppendHandle fp mode b
754 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
756 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
757 hIsBlockBuffered handle = do
758 htype <- readHandle handle
760 ErrorHandle ioError -> do
761 writeHandle handle htype
764 writeHandle handle htype
765 ioe_closedHandle handle
766 SemiClosedHandle _ _ -> do
767 writeHandle handle htype
768 ioe_closedHandle handle
770 other <- getBufferMode other
771 case bufferMode other of
772 Just (BlockBuffering size) -> do
773 writeHandle handle other
776 writeHandle handle other
777 return (False, Nothing)
779 constructErrorAndFail "hIsBlockBuffered"
781 hIsLineBuffered :: Handle -> IO Bool
782 hIsLineBuffered handle = do
783 htype <- readHandle handle
785 ErrorHandle ioError -> do
786 writeHandle handle htype
789 writeHandle handle htype
790 ioe_closedHandle handle
791 SemiClosedHandle _ _ -> do
792 writeHandle handle htype
793 ioe_closedHandle handle
795 other <- getBufferMode other
796 case bufferMode other of
797 Just LineBuffering -> do
798 writeHandle handle other
801 writeHandle handle other
804 constructErrorAndFail "hIsLineBuffered"
806 hIsNotBuffered :: Handle -> IO Bool
807 hIsNotBuffered handle = do
808 htype <- readHandle handle
810 ErrorHandle ioError -> do
811 writeHandle handle htype
814 writeHandle handle htype
815 ioe_closedHandle handle
816 SemiClosedHandle _ _ -> do
817 writeHandle handle htype
818 ioe_closedHandle handle
820 other <- getBufferMode other
821 case bufferMode other of
822 Just NoBuffering -> do
823 writeHandle handle other
826 writeHandle handle other
829 constructErrorAndFail "hIsNotBuffered"
831 hGetBuffering :: Handle -> IO BufferMode
832 hGetBuffering handle = do
833 htype <- readHandle handle
835 ErrorHandle ioError -> do
836 writeHandle handle htype
839 writeHandle handle htype
840 ioe_closedHandle handle
841 SemiClosedHandle _ _ -> do
842 writeHandle handle htype
843 ioe_closedHandle handle
845 other <- getBufferMode other
846 case bufferMode other of
848 writeHandle handle other
851 constructErrorAndFail "hGetBuffering"
853 hIsSeekable :: Handle -> IO Bool
854 hIsSeekable handle = do
855 htype <- readHandle handle
857 ErrorHandle ioError -> do
858 writeHandle handle htype
861 writeHandle handle htype
862 ioe_closedHandle handle
863 SemiClosedHandle _ _ -> do
864 writeHandle handle htype
865 ioe_closedHandle handle
866 AppendHandle _ _ _ -> do
867 writeHandle handle htype
870 rc <- _ccall_ seekFileP (filePtr other)
871 writeHandle handle htype
875 _ -> constructErrorAndFail "hIsSeekable"
879 %*********************************************************
881 \subsection{Miscellaneous}
883 %*********************************************************
885 These two functions are meant to get things out of @IOErrors@. They don't!
888 ioeGetFileName :: IOError -> Maybe FilePath
889 ioeGetErrorString :: IOError -> String
890 ioeGetHandle :: IOError -> Maybe Handle
892 ioeGetHandle (IOError h _ _) = h
893 ioeGetErrorString (IOError _ iot str) =
898 ioeGetFileName (IOError _ _ str) =
899 case span (/=':') str of
905 Internal function for creating an @IOError@ representing the
906 access of a closed file.
910 ioe_closedHandle :: Handle -> IO a
911 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")