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
485 BlockBuffering Nothing -> -2
486 BlockBuffering (Just n) -> n
488 #ifndef __PARALLEL_HASKELL__
489 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
491 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
493 hcon (ReadHandle _ _ _) = ReadHandle
494 hcon (WriteHandle _ _ _) = WriteHandle
495 hcon (AppendHandle _ _ _) = AppendHandle
496 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
499 Computation $flush hdl$ causes any items buffered for output in handle
500 {\em hdl} to be sent immediately to the operating system.
503 hFlush :: Handle -> IO ()
505 htype <- readHandle handle
507 ErrorHandle ioError -> do
508 writeHandle handle htype
511 writeHandle handle htype
512 ioe_closedHandle handle
513 SemiClosedHandle _ _ -> do
514 writeHandle handle htype
515 ioe_closedHandle handle
517 rc <- _ccall_ flushFile (filePtr other)
518 writeHandle handle (markHandle htype)
522 constructErrorAndFail "hFlush"
526 %*********************************************************
528 \subsection[Seeking]{Repositioning Handles}
530 %*********************************************************
533 data HandlePosn = HandlePosn Handle Int
535 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
536 deriving (Eq, Ord, Ix, Enum, Read, Show)
539 Computation $hGetPosn hdl$ returns the current I/O
540 position of {\em hdl} as an abstract position. Computation
541 $hSetPosn p$ sets the position of {\em hdl}
542 to a previously obtained position {\em p}.
545 hGetPosn :: Handle -> IO HandlePosn
547 htype <- readHandle handle
549 ErrorHandle ioError -> do
550 writeHandle handle htype
553 writeHandle handle htype
554 ioe_closedHandle handle
555 SemiClosedHandle _ _ -> do
556 writeHandle handle htype
557 ioe_closedHandle handle
559 posn <- _ccall_ getFilePosn (filePtr other)
560 writeHandle handle htype
562 return (HandlePosn handle posn)
564 constructErrorAndFail "hGetPosn"
566 hSetPosn :: HandlePosn -> IO ()
567 hSetPosn (HandlePosn handle posn) = do
568 htype <- readHandle handle
570 ErrorHandle ioError -> do
571 writeHandle handle htype
574 writeHandle handle htype
575 ioe_closedHandle handle
576 SemiClosedHandle _ _ -> do
577 writeHandle handle htype
578 ioe_closedHandle handle
579 AppendHandle _ _ _ -> do
580 writeHandle handle htype
581 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
583 rc <- _ccall_ setFilePosn (filePtr other) posn
584 writeHandle handle (markHandle htype)
588 constructErrorAndFail "hSetPosn"
591 Computation $hSeek hdl mode i$ sets the position of handle
592 {\em hdl} depending on $mode$. If {\em mode} is
594 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
595 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
596 the current position.
597 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
599 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
600 the beginning of the file.
603 Some handles may not be seekable $hIsSeekable$, or only support a
604 subset of the possible positioning operations (e.g. it may only be
605 possible to seek to the end of a tape, or to a positive offset from
606 the beginning or current position).
608 It is not possible to set a negative I/O position, or for a physical
609 file, an I/O position beyond the current end-of-file.
612 hSeek :: Handle -> SeekMode -> Integer -> IO ()
613 hSeek handle mode offset@(J# _ s# d#) = do
614 htype <- readHandle handle
616 ErrorHandle ioError -> do
617 writeHandle handle htype
620 writeHandle handle htype
621 ioe_closedHandle handle
622 SemiClosedHandle _ _ -> do
623 writeHandle handle htype
624 ioe_closedHandle handle
625 AppendHandle _ _ _ -> do
626 writeHandle handle htype
627 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
629 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
631 writeHandle handle (markHandle htype)
635 constructErrorAndFail "hSeek"
638 whence = case mode of
639 AbsoluteSeek -> ``SEEK_SET''
640 RelativeSeek -> ``SEEK_CUR''
641 SeekFromEnd -> ``SEEK_END''
644 %*********************************************************
646 \subsection[Query]{Handle Properties}
648 %*********************************************************
650 A number of operations return information about the properties of a
651 handle. Each of these operations returns $True$ if the
652 handle has the specified property, and $False$
655 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
656 {\em hdl} is not block-buffered. Otherwise it returns
657 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
658 $( Just n )$ for block-buffering of {\em n} bytes.
661 hIsOpen :: Handle -> IO Bool
663 htype <- readHandle handle
665 ErrorHandle ioError -> do
666 writeHandle handle htype
669 writeHandle handle htype
671 SemiClosedHandle _ _ -> do
672 writeHandle handle htype
675 writeHandle handle htype
678 hIsClosed :: Handle -> IO Bool
679 hIsClosed handle = do
680 htype <- readHandle handle
682 ErrorHandle ioError -> do
683 writeHandle handle htype
686 writeHandle handle htype
689 writeHandle handle htype
692 hIsReadable :: Handle -> IO Bool
693 hIsReadable handle = do
694 htype <- readHandle handle
696 ErrorHandle ioError -> do
697 writeHandle handle htype
700 writeHandle handle htype
701 ioe_closedHandle handle
702 SemiClosedHandle _ _ -> do
703 writeHandle handle htype
704 ioe_closedHandle handle
706 writeHandle handle htype
707 return (isReadable other)
709 isReadable (ReadHandle _ _ _) = True
710 isReadable (ReadWriteHandle _ _ _) = True
713 hIsWritable :: Handle -> IO Bool
714 hIsWritable handle = do
715 htype <- readHandle handle
717 ErrorHandle ioError -> do
718 writeHandle handle htype
721 writeHandle handle htype
722 ioe_closedHandle handle
723 SemiClosedHandle _ _ -> do
724 writeHandle handle htype
725 ioe_closedHandle handle
727 writeHandle handle htype
728 return (isWritable other)
730 isWritable (AppendHandle _ _ _) = True
731 isWritable (WriteHandle _ _ _) = True
732 isWritable (ReadWriteHandle _ _ _) = True
735 getBufferMode :: Handle__ -> IO Handle__
736 getBufferMode htype =
737 case bufferMode htype of
738 Just x -> return htype
740 rc <- _ccall_ getBufferMode (filePtr htype)
744 0 -> Just NoBuffering
745 -1 -> Just LineBuffering
746 -2 -> Just (BlockBuffering Nothing)
748 n -> Just (BlockBuffering (Just n))
749 return (case htype of
750 ReadHandle fp _ b -> ReadHandle fp mode b
751 WriteHandle fp _ b -> WriteHandle fp mode b
752 AppendHandle fp _ b -> AppendHandle fp mode b
753 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
755 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
756 hIsBlockBuffered handle = do
757 htype <- readHandle handle
759 ErrorHandle ioError -> do
760 writeHandle handle htype
763 writeHandle handle htype
764 ioe_closedHandle handle
765 SemiClosedHandle _ _ -> do
766 writeHandle handle htype
767 ioe_closedHandle handle
769 other <- getBufferMode other
770 case bufferMode other of
771 Just (BlockBuffering size) -> do
772 writeHandle handle other
775 writeHandle handle other
776 return (False, Nothing)
778 constructErrorAndFail "hIsBlockBuffered"
780 hIsLineBuffered :: Handle -> IO Bool
781 hIsLineBuffered handle = do
782 htype <- readHandle handle
784 ErrorHandle ioError -> do
785 writeHandle handle htype
788 writeHandle handle htype
789 ioe_closedHandle handle
790 SemiClosedHandle _ _ -> do
791 writeHandle handle htype
792 ioe_closedHandle handle
794 other <- getBufferMode other
795 case bufferMode other of
796 Just LineBuffering -> do
797 writeHandle handle other
800 writeHandle handle other
803 constructErrorAndFail "hIsLineBuffered"
805 hIsNotBuffered :: Handle -> IO Bool
806 hIsNotBuffered handle = do
807 htype <- readHandle handle
809 ErrorHandle ioError -> do
810 writeHandle handle htype
813 writeHandle handle htype
814 ioe_closedHandle handle
815 SemiClosedHandle _ _ -> do
816 writeHandle handle htype
817 ioe_closedHandle handle
819 other <- getBufferMode other
820 case bufferMode other of
821 Just NoBuffering -> do
822 writeHandle handle other
825 writeHandle handle other
828 constructErrorAndFail "hIsNotBuffered"
830 hGetBuffering :: Handle -> IO BufferMode
831 hGetBuffering handle = do
832 htype <- readHandle handle
834 ErrorHandle ioError -> do
835 writeHandle handle htype
838 writeHandle handle htype
839 ioe_closedHandle handle
840 SemiClosedHandle _ _ -> do
841 writeHandle handle htype
842 ioe_closedHandle handle
844 other <- getBufferMode other
845 case bufferMode other of
847 writeHandle handle other
850 constructErrorAndFail "hGetBuffering"
852 hIsSeekable :: Handle -> IO Bool
853 hIsSeekable handle = do
854 htype <- readHandle handle
856 ErrorHandle ioError -> do
857 writeHandle handle htype
860 writeHandle handle htype
861 ioe_closedHandle handle
862 SemiClosedHandle _ _ -> do
863 writeHandle handle htype
864 ioe_closedHandle handle
865 AppendHandle _ _ _ -> do
866 writeHandle handle htype
869 rc <- _ccall_ seekFileP (filePtr other)
870 writeHandle handle htype
874 _ -> constructErrorAndFail "hIsSeekable"
878 %*********************************************************
880 \subsection{Miscellaneous}
882 %*********************************************************
884 These two functions are meant to get things out of @IOErrors@. They don't!
887 ioeGetFileName :: IOError -> Maybe FilePath
888 ioeGetErrorString :: IOError -> String
889 ioeGetHandle :: IOError -> Maybe Handle
891 ioeGetHandle (IOError h _ _) = h
892 ioeGetErrorString (IOError _ iot str) =
897 ioeGetFileName (IOError _ _ str) =
898 case span (/=':') str of
904 Internal function for creating an @IOError@ representing the
905 access of a closed file.
909 ioe_closedHandle :: Handle -> IO a
910 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")