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" #-}
19 import ArrBase ( ByteArray(..), newVar, readVar, writeVar )
20 import PrelRead ( Read )
21 import PrelList (span)
24 import Unsafe ( unsafePerformIO )
32 #ifndef __PARALLEL_HASKELL__
33 import Foreign ( ForeignObj, makeForeignObj, writeForeignObj )
36 #if defined(__CONCURRENT_HASKELL__)
42 %*********************************************************
44 \subsection{Types @FilePath@, @Handle@, @Handle__@}
46 %*********************************************************
48 The @Handle@ and @Handle__@ types are defined in @IOBase@.
51 type FilePath = String
53 {-# INLINE newHandle #-}
54 {-# INLINE readHandle #-}
55 {-# INLINE writeHandle #-}
56 newHandle :: Handle__ -> IO Handle
57 readHandle :: Handle -> IO Handle__
58 writeHandle :: Handle -> Handle__ -> IO ()
60 #if defined(__CONCURRENT_HASKELL__)
62 -- Use MVars for concurrent Haskell
63 newHandle hc = newMVar hc >>= \ h ->
66 readHandle (Handle h) = takeMVar h
67 writeHandle (Handle h) hc = putMVar h hc
71 -- Use ordinary MutableVars for non-concurrent Haskell
72 newHandle hc = stToIO (newVar hc >>= \ h ->
75 readHandle (Handle h) = stToIO (readVar h)
76 writeHandle (Handle h) hc = stToIO (writeVar h hc)
81 %*********************************************************
83 \subsection{Functions}
85 %*********************************************************
88 #ifndef __PARALLEL_HASKELL__
89 filePtr :: Handle__ -> ForeignObj
91 filePtr :: Handle__ -> Addr
93 filePtr (SemiClosedHandle fp _) = fp
94 filePtr (ReadHandle fp _ _) = fp
95 filePtr (WriteHandle fp _ _) = fp
96 filePtr (AppendHandle fp _ _) = fp
97 filePtr (ReadWriteHandle fp _ _) = fp
99 bufferMode :: Handle__ -> Maybe BufferMode
100 bufferMode (ReadHandle _ m _) = m
101 bufferMode (WriteHandle _ m _) = m
102 bufferMode (AppendHandle _ m _) = m
103 bufferMode (ReadWriteHandle _ m _) = m
105 markHandle :: Handle__ -> Handle__
106 markHandle h@(ReadHandle fp m b)
108 | otherwise = ReadHandle fp m True
109 markHandle h@(WriteHandle fp m b)
111 | otherwise = WriteHandle fp m True
112 markHandle h@(AppendHandle fp m b)
114 | otherwise = AppendHandle fp m True
115 markHandle h@(ReadWriteHandle fp m b)
117 | otherwise = ReadWriteHandle fp m True
120 -------------------------------------------
122 %*********************************************************
124 \subsection[StdHandles]{Standard handles}
126 %*********************************************************
128 Three handles are allocated during program initialisation. The first
129 two manage input or output from the Haskell program's standard input
130 or output channel respectively. The third manages output to the
131 standard error channel. These handles are initially open.
134 stdin, stdout, stderr :: Handle
136 stdin = unsafePerformIO (do
137 rc <- _ccall_ getLock (``stdin''::Addr) 0
139 0 -> newHandle ClosedHandle
141 #ifndef __PARALLEL_HASKELL__
142 fp <- makeForeignObj (``stdin''::Addr) (``&freeStdFile''::Addr)
143 newHandle (ReadHandle fp Nothing False)
145 newHandle (ReadHandle ``stdin'' Nothing False)
147 _ -> do ioError <- constructError "stdin"
148 newHandle (ErrorHandle ioError)
151 stdout = unsafePerformIO (do
152 rc <- _ccall_ getLock (``stdout''::Addr) 1
154 0 -> newHandle ClosedHandle
156 #ifndef __PARALLEL_HASKELL__
157 fp <- makeForeignObj (``stdout''::Addr) (``&freeStdFile''::Addr)
158 newHandle (WriteHandle fp Nothing False)
160 newHandle (WriteHandle ``stdout'' Nothing False)
162 _ -> do ioError <- constructError "stdout"
163 newHandle (ErrorHandle ioError)
166 stderr = unsafePerformIO (do
167 rc <- _ccall_ getLock (``stderr''::Addr) 1
169 0 -> newHandle ClosedHandle
171 #ifndef __PARALLEL_HASKELL__
172 fp <- makeForeignObj (``stderr''::Addr) (``&freeStdFile''::Addr)
173 newHandle (WriteHandle fp (Just NoBuffering) False)
175 newHandle (WriteHandle ``stderr'' (Just NoBuffering) False)
177 _ -> do ioError <- constructError "stderr"
178 newHandle (ErrorHandle ioError)
182 %*********************************************************
184 \subsection[OpeningClosing]{Opening and Closing Files}
186 %*********************************************************
189 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
190 deriving (Eq, Ord, Ix, Enum, Read, Show)
192 openFile :: FilePath -> IOMode -> IO Handle
195 ptr <- _ccall_ openFile f m'
196 if ptr /= ``NULL'' then do
197 #ifndef __PARALLEL_HASKELL__
198 fp <- makeForeignObj ptr ((``&freeFile'')::Addr)
199 newHandle (htype fp Nothing False)
201 newHandle (htype ptr Nothing False)
204 ioError@(IOError hn iot msg) <- constructError "openFile"
206 improved_error -- a HACK, I guess
208 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
209 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
210 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
218 ReadWriteMode -> "r+"
221 ReadMode -> ReadHandle
222 WriteMode -> WriteHandle
223 AppendMode -> AppendHandle
224 ReadWriteMode -> ReadWriteHandle
227 Computation $openFile file mode$ allocates and returns a new, open
228 handle to manage the file {\em file}. It manages input if {\em mode}
229 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
230 and both input and output if mode is $ReadWriteMode$.
232 If the file does not exist and it is opened for output, it should be
233 created as a new file. If {\em mode} is $WriteMode$ and the file
234 already exists, then it should be truncated to zero length. The
235 handle is positioned at the end of the file if {\em mode} is
236 $AppendMode$, and otherwise at the beginning (in which case its
237 internal position is 0).
239 Implementations should enforce, locally to the Haskell process,
240 multiple-reader single-writer locking on files, which is to say that
241 there may either be many handles on the same file which manage input,
242 or just one handle on the file which manages output. If any open or
243 semi-closed handle is managing a file for output, no new handle can be
244 allocated for that file. If any open or semi-closed handle is
245 managing a file for input, new handles can only be allocated if they
246 do not manage output.
248 Two files are the same if they have the same absolute name. An
249 implementation is free to impose stricter conditions.
252 hClose :: Handle -> IO ()
255 htype <- readHandle handle
257 ErrorHandle ioError -> do
258 writeHandle handle htype
261 writeHandle handle htype
262 ioe_closedHandle handle
263 SemiClosedHandle fp (buf,_) -> do
264 (if buf /= ``NULL'' then
268 fp_a <- _casm_ `` %r = (char *)%0; '' fp
269 if fp_a /= (``NULL''::Addr) then do
270 -- Under what condition can this be NULL?
271 rc <- _ccall_ closeFile fp
272 {- We explicitly close a file object so that we can be told
273 if there were any errors. Note that after @hClose@
274 has been performed, the ForeignObj embedded in the Handle
275 is still lying around in the heap, so care is taken
276 to avoid closing the file object when the ForeignObj
279 #ifndef __PARALLEL_HASKELL__
280 -- Mark the foreign object data value as
281 -- gone to the finaliser (freeFile())
282 writeForeignObj fp ``NULL''
284 writeHandle handle ClosedHandle
286 writeHandle handle htype
287 constructErrorAndFail "hClose"
289 else writeHandle handle htype
292 let fp = filePtr other
293 rc <- _ccall_ closeFile fp
295 #ifndef __PARALLEL_HASKELL__
296 -- Mark the foreign object data
297 writeForeignObj fp ``NULL''
299 writeHandle handle ClosedHandle
301 writeHandle handle htype
302 constructErrorAndFail "hClose"
305 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
306 computation finishes, any items buffered for output and not already
307 sent to the operating system are flushed as for $flush$.
309 %*********************************************************
311 \subsection[EOF]{Detecting the End of Input}
313 %*********************************************************
316 For a handle {\em hdl} which attached to a physical file, $hFileSize
317 hdl$ returns the size of {\em hdl} in terms of the number of items
318 which can be read from {\em hdl}.
321 hFileSize :: Handle -> IO Integer
322 hFileSize handle = do
323 htype <- readHandle handle
325 ErrorHandle ioError -> do
326 writeHandle handle htype
329 writeHandle handle htype
330 ioe_closedHandle handle
331 SemiClosedHandle _ _ -> do
332 writeHandle handle htype
333 ioe_closedHandle handle
335 -- HACK! We build a unique MP_INT of the right shape to hold
336 -- a single unsigned word, and we let the C routine
337 -- change the data bits
339 -- For some reason, this fails to typecheck if converted to a do
341 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
342 case int2Integer# hack# of
343 result@(J# _ _ d#) -> do
344 let bogus_bounds = (error "fileSize"::(Int,Int))
345 rc <- _ccall_ fileSize (filePtr other)
346 (ByteArray bogus_bounds d#)
347 writeHandle handle htype
351 constructErrorAndFail "hFileSize"
354 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
355 $True$ if no further input can be taken from {\em hdl} or for a
356 physical file, if the current I/O position is equal to the length of
357 the file. Otherwise, it returns $False$.
360 hIsEOF :: Handle -> IO Bool
362 htype <- readHandle handle
364 ErrorHandle ioError -> do
365 writeHandle handle htype
368 writeHandle handle htype
369 ioe_closedHandle handle
370 SemiClosedHandle _ _ -> do
371 writeHandle handle htype
372 ioe_closedHandle handle
373 WriteHandle _ _ _ -> do
374 writeHandle handle htype
375 fail (IOError (Just handle) IllegalOperation
376 "handle is not open for reading")
377 AppendHandle _ _ _ -> do
378 writeHandle handle htype
379 fail (IOError (Just handle) IllegalOperation
380 "handle is not open for reading")
382 rc <- _ccall_ fileEOF (filePtr other)
383 writeHandle handle (markHandle htype)
387 _ -> constructErrorAndFail "hIsEOF"
393 %*********************************************************
395 \subsection[Buffering]{Buffering Operations}
397 %*********************************************************
399 Three kinds of buffering are supported: line-buffering,
400 block-buffering or no-buffering. See @IOBase@ for definition
401 and further explanation of what the type represent.
403 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
404 handle {\em hdl} on subsequent reads and writes.
408 If {\em mode} is @LineBuffering@, line-buffering should be
411 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
412 should be enabled if possible. The size of the buffer is {\em n} items
413 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
415 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
418 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
419 to @NoBuffering@, then any items in the output buffer are written to
420 the device, and any items in the input buffer are discarded. The
421 default buffering mode when a handle is opened is
422 implementation-dependent and may depend on the object which is
423 attached to that handle.
426 hSetBuffering :: Handle -> BufferMode -> IO ()
428 hSetBuffering handle mode =
430 BlockBuffering (Just n)
431 | n <= 0 -> fail (IOError (Just handle) InvalidArgument
432 "illegal buffer size")
434 htype <- readHandle handle
435 if isMarked htype then do
436 writeHandle handle htype
437 fail (IOError (Just handle)
439 "can't set buffering for a dirty handle")
442 ErrorHandle ioError -> do
443 writeHandle handle htype
446 writeHandle handle htype
447 ioe_closedHandle handle
448 SemiClosedHandle _ _ -> do
449 writeHandle handle htype
450 ioe_closedHandle handle
452 rc <- _ccall_ setBuffering (filePtr other) bsize
454 writeHandle handle ((hcon other) (filePtr other)
457 writeHandle handle htype
458 constructErrorAndFail "hSetBuffering"
461 isMarked :: Handle__ -> Bool
462 isMarked (ReadHandle fp m b) = b
463 isMarked (WriteHandle fp m b) = b
464 isMarked (AppendHandle fp m b) = b
465 isMarked (ReadWriteHandle fp m b) = b
471 BlockBuffering Nothing -> -2
472 BlockBuffering (Just n) -> n
474 #ifndef __PARALLEL_HASKELL__
475 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
477 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
479 hcon (ReadHandle _ _ _) = ReadHandle
480 hcon (WriteHandle _ _ _) = WriteHandle
481 hcon (AppendHandle _ _ _) = AppendHandle
482 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
485 Computation $flush hdl$ causes any items buffered for output in handle
486 {\em hdl} to be sent immediately to the operating system.
489 hFlush :: Handle -> IO ()
491 htype <- readHandle handle
493 ErrorHandle ioError -> do
494 writeHandle handle htype
497 writeHandle handle htype
498 ioe_closedHandle handle
499 SemiClosedHandle _ _ -> do
500 writeHandle handle htype
501 ioe_closedHandle handle
503 rc <- _ccall_ flushFile (filePtr other)
504 writeHandle handle (markHandle htype)
508 constructErrorAndFail "hFlush"
512 %*********************************************************
514 \subsection[Seeking]{Repositioning Handles}
516 %*********************************************************
519 data HandlePosn = HandlePosn Handle Int
521 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
522 deriving (Eq, Ord, Ix, Enum, Read, Show)
525 Computation $hGetPosn hdl$ returns the current I/O
526 position of {\em hdl} as an abstract position. Computation
527 $hSetPosn p$ sets the position of {\em hdl}
528 to a previously obtained position {\em p}.
531 hGetPosn :: Handle -> IO HandlePosn
533 htype <- readHandle handle
535 ErrorHandle ioError -> do
536 writeHandle handle htype
539 writeHandle handle htype
540 ioe_closedHandle handle
541 SemiClosedHandle _ _ -> do
542 writeHandle handle htype
543 ioe_closedHandle handle
545 posn <- _ccall_ getFilePosn (filePtr other)
546 writeHandle handle htype
548 return (HandlePosn handle posn)
550 constructErrorAndFail "hGetPosn"
552 hSetPosn :: HandlePosn -> IO ()
553 hSetPosn (HandlePosn handle posn) = do
554 htype <- readHandle handle
556 ErrorHandle ioError -> do
557 writeHandle handle htype
560 writeHandle handle htype
561 ioe_closedHandle handle
562 SemiClosedHandle _ _ -> do
563 writeHandle handle htype
564 ioe_closedHandle handle
565 AppendHandle _ _ _ -> do
566 writeHandle handle htype
567 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
569 rc <- _ccall_ setFilePosn (filePtr other) posn
570 writeHandle handle (markHandle htype)
574 constructErrorAndFail "hSetPosn"
577 Computation $hSeek hdl mode i$ sets the position of handle
578 {\em hdl} depending on $mode$. If {\em mode} is
580 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
581 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
582 the current position.
583 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
585 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
586 the beginning of the file.
589 Some handles may not be seekable $hIsSeekable$, or only support a
590 subset of the possible positioning operations (e.g. it may only be
591 possible to seek to the end of a tape, or to a positive offset from
592 the beginning or current position).
594 It is not possible to set a negative I/O position, or for a physical
595 file, an I/O position beyond the current end-of-file.
598 hSeek :: Handle -> SeekMode -> Integer -> IO ()
599 hSeek handle mode offset@(J# _ s# d#) = do
600 htype <- readHandle handle
602 ErrorHandle ioError -> do
603 writeHandle handle htype
606 writeHandle handle htype
607 ioe_closedHandle handle
608 SemiClosedHandle _ _ -> do
609 writeHandle handle htype
610 ioe_closedHandle handle
611 AppendHandle _ _ _ -> do
612 writeHandle handle htype
613 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
615 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
617 writeHandle handle (markHandle htype)
621 constructErrorAndFail "hSeek"
624 whence = case mode of
625 AbsoluteSeek -> ``SEEK_SET''
626 RelativeSeek -> ``SEEK_CUR''
627 SeekFromEnd -> ``SEEK_END''
630 %*********************************************************
632 \subsection[Query]{Handle Properties}
634 %*********************************************************
636 A number of operations return information about the properties of a
637 handle. Each of these operations returns $True$ if the
638 handle has the specified property, and $False$
641 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
642 {\em hdl} is not block-buffered. Otherwise it returns
643 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
644 $( Just n )$ for block-buffering of {\em n} bytes.
647 hIsOpen :: Handle -> IO Bool
649 htype <- readHandle handle
651 ErrorHandle ioError -> do
652 writeHandle handle htype
655 writeHandle handle htype
657 SemiClosedHandle _ _ -> do
658 writeHandle handle htype
661 writeHandle handle htype
664 hIsClosed :: Handle -> IO Bool
665 hIsClosed handle = do
666 htype <- readHandle handle
668 ErrorHandle ioError -> do
669 writeHandle handle htype
672 writeHandle handle htype
675 writeHandle handle htype
678 hIsReadable :: Handle -> IO Bool
679 hIsReadable handle = do
680 htype <- readHandle handle
682 ErrorHandle ioError -> do
683 writeHandle handle htype
686 writeHandle handle htype
687 ioe_closedHandle handle
688 SemiClosedHandle _ _ -> do
689 writeHandle handle htype
690 ioe_closedHandle handle
692 writeHandle handle htype
693 return (isReadable other)
695 isReadable (ReadHandle _ _ _) = True
696 isReadable (ReadWriteHandle _ _ _) = True
699 hIsWritable :: Handle -> IO Bool
700 hIsWritable handle = do
701 htype <- readHandle handle
703 ErrorHandle ioError -> do
704 writeHandle handle htype
707 writeHandle handle htype
708 ioe_closedHandle handle
709 SemiClosedHandle _ _ -> do
710 writeHandle handle htype
711 ioe_closedHandle handle
713 writeHandle handle htype
714 return (isWritable other)
716 isWritable (AppendHandle _ _ _) = True
717 isWritable (WriteHandle _ _ _) = True
718 isWritable (ReadWriteHandle _ _ _) = True
721 getBufferMode :: Handle__ -> IO Handle__
722 getBufferMode htype =
723 case bufferMode htype of
724 Just x -> return htype
726 rc <- _ccall_ getBufferMode (filePtr htype)
730 0 -> Just NoBuffering
731 -1 -> Just LineBuffering
732 -2 -> Just (BlockBuffering Nothing)
734 n -> Just (BlockBuffering (Just n))
735 return (case htype of
736 ReadHandle fp _ b -> ReadHandle fp mode b
737 WriteHandle fp _ b -> WriteHandle fp mode b
738 AppendHandle fp _ b -> AppendHandle fp mode b
739 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
741 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
742 hIsBlockBuffered handle = do
743 htype <- readHandle handle
745 ErrorHandle ioError -> do
746 writeHandle handle htype
749 writeHandle handle htype
750 ioe_closedHandle handle
751 SemiClosedHandle _ _ -> do
752 writeHandle handle htype
753 ioe_closedHandle handle
755 other <- getBufferMode other
756 case bufferMode other of
757 Just (BlockBuffering size) -> do
758 writeHandle handle other
761 writeHandle handle other
762 return (False, Nothing)
764 constructErrorAndFail "hIsBlockBuffered"
766 hIsLineBuffered :: Handle -> IO Bool
767 hIsLineBuffered handle = do
768 htype <- readHandle handle
770 ErrorHandle ioError -> do
771 writeHandle handle htype
774 writeHandle handle htype
775 ioe_closedHandle handle
776 SemiClosedHandle _ _ -> do
777 writeHandle handle htype
778 ioe_closedHandle handle
780 other <- getBufferMode other
781 case bufferMode other of
782 Just LineBuffering -> do
783 writeHandle handle other
786 writeHandle handle other
789 constructErrorAndFail "hIsLineBuffered"
791 hIsNotBuffered :: Handle -> IO Bool
792 hIsNotBuffered handle = do
793 htype <- readHandle handle
795 ErrorHandle ioError -> do
796 writeHandle handle htype
799 writeHandle handle htype
800 ioe_closedHandle handle
801 SemiClosedHandle _ _ -> do
802 writeHandle handle htype
803 ioe_closedHandle handle
805 other <- getBufferMode other
806 case bufferMode other of
807 Just NoBuffering -> do
808 writeHandle handle other
811 writeHandle handle other
814 constructErrorAndFail "hIsNotBuffered"
816 hGetBuffering :: Handle -> IO BufferMode
817 hGetBuffering handle = do
818 htype <- readHandle handle
820 ErrorHandle ioError -> do
821 writeHandle handle htype
824 writeHandle handle htype
825 ioe_closedHandle handle
826 SemiClosedHandle _ _ -> do
827 writeHandle handle htype
828 ioe_closedHandle handle
830 other <- getBufferMode other
831 case bufferMode other of
833 writeHandle handle other
836 constructErrorAndFail "hGetBuffering"
838 hIsSeekable :: Handle -> IO Bool
839 hIsSeekable handle = do
840 htype <- readHandle handle
842 ErrorHandle ioError -> do
843 writeHandle handle htype
846 writeHandle handle htype
847 ioe_closedHandle handle
848 SemiClosedHandle _ _ -> do
849 writeHandle handle htype
850 ioe_closedHandle handle
851 AppendHandle _ _ _ -> do
852 writeHandle handle htype
855 rc <- _ccall_ seekFileP (filePtr other)
856 writeHandle handle htype
860 _ -> constructErrorAndFail "hIsSeekable"
864 %*********************************************************
866 \subsection{Miscellaneous}
868 %*********************************************************
870 These two functions are meant to get things out of @IOErrors@. They don't!
873 ioeGetFileName :: IOError -> Maybe FilePath
874 ioeGetErrorString :: IOError -> String
875 ioeGetHandle :: IOError -> Maybe Handle
877 ioeGetHandle (IOError h _ _) = h
878 ioeGetErrorString (IOError _ iot str) =
883 ioeGetFileName (IOError _ _ str) =
884 case span (/=':') str of
890 Internal function for creating an @IOError@ representing the
891 access of a closed file.
895 ioe_closedHandle :: Handle -> IO a
896 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")