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__)
65 newHandle v = stToIO (newVar v)
66 readHandle h = stToIO (readVar h)
67 writeHandle h v = stToIO (writeVar h v)
72 %*********************************************************
74 \subsection{Functions}
76 %*********************************************************
79 #ifndef __PARALLEL_HASKELL__
80 filePtr :: Handle__ -> ForeignObj
82 filePtr :: Handle__ -> Addr
84 filePtr (SemiClosedHandle fp _) = fp
85 filePtr (ReadHandle fp _ _) = fp
86 filePtr (WriteHandle fp _ _) = fp
87 filePtr (AppendHandle fp _ _) = fp
88 filePtr (ReadWriteHandle fp _ _) = fp
90 bufferMode :: Handle__ -> Maybe BufferMode
91 bufferMode (ReadHandle _ m _) = m
92 bufferMode (WriteHandle _ m _) = m
93 bufferMode (AppendHandle _ m _) = m
94 bufferMode (ReadWriteHandle _ m _) = m
96 markHandle :: Handle__ -> Handle__
97 markHandle h@(ReadHandle fp m b)
99 | otherwise = ReadHandle fp m True
100 markHandle h@(WriteHandle fp m b)
102 | otherwise = WriteHandle fp m True
103 markHandle h@(AppendHandle fp m b)
105 | otherwise = AppendHandle fp m True
106 markHandle h@(ReadWriteHandle fp m b)
108 | otherwise = ReadWriteHandle fp m True
111 -------------------------------------------
113 %*********************************************************
115 \subsection[StdHandles]{Standard handles}
117 %*********************************************************
119 Three handles are allocated during program initialisation. The first
120 two manage input or output from the Haskell program's standard input
121 or output channel respectively. The third manages output to the
122 standard error channel. These handles are initially open.
125 stdin, stdout, stderr :: Handle
127 stdin = unsafePerformIO (do
128 rc <- _ccall_ getLock (``stdin''::Addr) 0
130 0 -> newHandle ClosedHandle
132 #ifndef __PARALLEL_HASKELL__
133 fp <- makeForeignObj (``stdin''::Addr) (``&freeStdFile''::Addr)
134 newHandle (ReadHandle fp Nothing False)
136 newHandle (ReadHandle ``stdin'' Nothing False)
138 _ -> do ioError <- constructError "stdin"
139 newHandle (ErrorHandle ioError)
142 stdout = unsafePerformIO (do
143 rc <- _ccall_ getLock (``stdout''::Addr) 1
145 0 -> newHandle ClosedHandle
147 #ifndef __PARALLEL_HASKELL__
148 fp <- makeForeignObj (``stdout''::Addr) (``&freeStdFile''::Addr)
149 newHandle (WriteHandle fp Nothing False)
151 newHandle (WriteHandle ``stdout'' Nothing False)
153 _ -> do ioError <- constructError "stdout"
154 newHandle (ErrorHandle ioError)
157 stderr = unsafePerformIO (do
158 rc <- _ccall_ getLock (``stderr''::Addr) 1
160 0 -> newHandle ClosedHandle
162 #ifndef __PARALLEL_HASKELL__
163 fp <- makeForeignObj (``stderr''::Addr) (``&freeStdFile''::Addr)
164 newHandle (WriteHandle fp (Just NoBuffering) False)
166 newHandle (WriteHandle ``stderr'' (Just NoBuffering) False)
168 _ -> do ioError <- constructError "stderr"
169 newHandle (ErrorHandle ioError)
173 %*********************************************************
175 \subsection[OpeningClosing]{Opening and Closing Files}
177 %*********************************************************
180 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
181 deriving (Eq, Ord, Ix, Enum, Read, Show)
183 openFile :: FilePath -> IOMode -> IO Handle
186 ptr <- _ccall_ openFile f m'
187 if ptr /= ``NULL'' then do
188 #ifndef __PARALLEL_HASKELL__
189 fp <- makeForeignObj ptr ((``&freeFile'')::Addr)
190 newHandle (htype fp Nothing False)
192 newHandle (htype ptr Nothing False)
195 ioError@(IOError hn iot msg) <- constructError "openFile"
197 improved_error -- a HACK, I guess
199 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
200 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
201 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
209 ReadWriteMode -> "r+"
212 ReadMode -> ReadHandle
213 WriteMode -> WriteHandle
214 AppendMode -> AppendHandle
215 ReadWriteMode -> ReadWriteHandle
218 Computation $openFile file mode$ allocates and returns a new, open
219 handle to manage the file {\em file}. It manages input if {\em mode}
220 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
221 and both input and output if mode is $ReadWriteMode$.
223 If the file does not exist and it is opened for output, it should be
224 created as a new file. If {\em mode} is $WriteMode$ and the file
225 already exists, then it should be truncated to zero length. The
226 handle is positioned at the end of the file if {\em mode} is
227 $AppendMode$, and otherwise at the beginning (in which case its
228 internal position is 0).
230 Implementations should enforce, locally to the Haskell process,
231 multiple-reader single-writer locking on files, which is to say that
232 there may either be many handles on the same file which manage input,
233 or just one handle on the file which manages output. If any open or
234 semi-closed handle is managing a file for output, no new handle can be
235 allocated for that file. If any open or semi-closed handle is
236 managing a file for input, new handles can only be allocated if they
237 do not manage output.
239 Two files are the same if they have the same absolute name. An
240 implementation is free to impose stricter conditions.
243 hClose :: Handle -> IO ()
246 htype <- readHandle handle
248 ErrorHandle ioError -> do
249 writeHandle handle htype
252 writeHandle handle htype
253 ioe_closedHandle handle
254 SemiClosedHandle fp (buf,_) -> do
255 (if buf /= ``NULL'' then
259 fp_a <- _casm_ `` %r = (char *)%0; '' fp
260 if fp_a /= (``NULL''::Addr) then do
261 -- Under what condition can this be NULL?
262 rc <- _ccall_ closeFile fp
263 {- We explicitly close a file object so that we can be told
264 if there were any errors. Note that after @hClose@
265 has been performed, the ForeignObj embedded in the Handle
266 is still lying around in the heap, so care is taken
267 to avoid closing the file object when the ForeignObj
270 #ifndef __PARALLEL_HASKELL__
271 -- Mark the foreign object data value as
272 -- gone to the finaliser (freeFile())
273 writeForeignObj fp ``NULL''
275 writeHandle handle ClosedHandle
277 writeHandle handle htype
278 constructErrorAndFail "hClose"
280 else writeHandle handle htype
283 let fp = filePtr other
284 rc <- _ccall_ closeFile fp
286 #ifndef __PARALLEL_HASKELL__
287 -- Mark the foreign object data
288 writeForeignObj fp ``NULL''
290 writeHandle handle ClosedHandle
292 writeHandle handle htype
293 constructErrorAndFail "hClose"
296 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
297 computation finishes, any items buffered for output and not already
298 sent to the operating system are flushed as for $flush$.
300 %*********************************************************
302 \subsection[EOF]{Detecting the End of Input}
304 %*********************************************************
307 For a handle {\em hdl} which attached to a physical file, $hFileSize
308 hdl$ returns the size of {\em hdl} in terms of the number of items
309 which can be read from {\em hdl}.
312 hFileSize :: Handle -> IO Integer
313 hFileSize handle = do
314 htype <- readHandle handle
316 ErrorHandle ioError -> do
317 writeHandle handle htype
320 writeHandle handle htype
321 ioe_closedHandle handle
322 SemiClosedHandle _ _ -> do
323 writeHandle handle htype
324 ioe_closedHandle handle
326 -- HACK! We build a unique MP_INT of the right shape to hold
327 -- a single unsigned word, and we let the C routine
328 -- change the data bits
330 -- For some reason, this fails to typecheck if converted to a do
332 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
333 case int2Integer# hack# of
334 result@(J# _ _ d#) -> do
335 let bogus_bounds = (error "fileSize"::(Int,Int))
336 rc <- _ccall_ fileSize (filePtr other)
337 (ByteArray bogus_bounds d#)
338 writeHandle handle htype
342 constructErrorAndFail "hFileSize"
345 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
346 $True$ if no further input can be taken from {\em hdl} or for a
347 physical file, if the current I/O position is equal to the length of
348 the file. Otherwise, it returns $False$.
351 hIsEOF :: Handle -> IO Bool
353 htype <- readHandle handle
355 ErrorHandle ioError -> do
356 writeHandle handle htype
359 writeHandle handle htype
360 ioe_closedHandle handle
361 SemiClosedHandle _ _ -> do
362 writeHandle handle htype
363 ioe_closedHandle handle
364 WriteHandle _ _ _ -> do
365 writeHandle handle htype
366 fail (IOError (Just handle) IllegalOperation
367 "handle is not open for reading")
368 AppendHandle _ _ _ -> do
369 writeHandle handle htype
370 fail (IOError (Just handle) IllegalOperation
371 "handle is not open for reading")
373 rc <- _ccall_ fileEOF (filePtr other)
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
423 "illegal buffer size")
425 htype <- readHandle handle
426 if isMarked htype then do
427 writeHandle handle htype
428 fail (IOError (Just handle)
430 "can't set buffering for a dirty handle")
433 ErrorHandle ioError -> do
434 writeHandle handle htype
437 writeHandle handle htype
438 ioe_closedHandle handle
439 SemiClosedHandle _ _ -> do
440 writeHandle handle htype
441 ioe_closedHandle handle
443 rc <- _ccall_ setBuffering (filePtr other) bsize
445 writeHandle handle ((hcon other) (filePtr other)
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
465 #ifndef __PARALLEL_HASKELL__
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 htype <- readHandle handle
484 ErrorHandle ioError -> do
485 writeHandle handle htype
488 writeHandle handle htype
489 ioe_closedHandle handle
490 SemiClosedHandle _ _ -> do
491 writeHandle handle htype
492 ioe_closedHandle handle
494 rc <- _ccall_ flushFile (filePtr other)
495 writeHandle handle (markHandle htype)
499 constructErrorAndFail "hFlush"
503 %*********************************************************
505 \subsection[Seeking]{Repositioning Handles}
507 %*********************************************************
510 data HandlePosn = HandlePosn Handle Int
512 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
513 deriving (Eq, Ord, Ix, Enum, Read, Show)
516 Computation $hGetPosn hdl$ returns the current I/O
517 position of {\em hdl} as an abstract position. Computation
518 $hSetPosn p$ sets the position of {\em hdl}
519 to a previously obtained position {\em p}.
522 hGetPosn :: Handle -> IO HandlePosn
524 htype <- readHandle handle
526 ErrorHandle ioError -> do
527 writeHandle handle htype
530 writeHandle handle htype
531 ioe_closedHandle handle
532 SemiClosedHandle _ _ -> do
533 writeHandle handle htype
534 ioe_closedHandle handle
536 posn <- _ccall_ getFilePosn (filePtr other)
537 writeHandle handle htype
539 return (HandlePosn handle posn)
541 constructErrorAndFail "hGetPosn"
543 hSetPosn :: HandlePosn -> IO ()
544 hSetPosn (HandlePosn handle posn) = do
545 htype <- readHandle handle
547 ErrorHandle ioError -> do
548 writeHandle handle htype
551 writeHandle handle htype
552 ioe_closedHandle handle
553 SemiClosedHandle _ _ -> do
554 writeHandle handle htype
555 ioe_closedHandle handle
556 AppendHandle _ _ _ -> do
557 writeHandle handle htype
558 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
560 rc <- _ccall_ setFilePosn (filePtr other) posn
561 writeHandle handle (markHandle htype)
565 constructErrorAndFail "hSetPosn"
568 Computation $hSeek hdl mode i$ sets the position of handle
569 {\em hdl} depending on $mode$. If {\em mode} is
571 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
572 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
573 the current position.
574 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
576 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
577 the beginning of the file.
580 Some handles may not be seekable $hIsSeekable$, or only support a
581 subset of the possible positioning operations (e.g. it may only be
582 possible to seek to the end of a tape, or to a positive offset from
583 the beginning or current position).
585 It is not possible to set a negative I/O position, or for a physical
586 file, an I/O position beyond the current end-of-file.
589 hSeek :: Handle -> SeekMode -> Integer -> IO ()
590 hSeek handle mode offset@(J# _ s# d#) = do
591 htype <- readHandle handle
593 ErrorHandle ioError -> do
594 writeHandle handle htype
597 writeHandle handle htype
598 ioe_closedHandle handle
599 SemiClosedHandle _ _ -> do
600 writeHandle handle htype
601 ioe_closedHandle handle
602 AppendHandle _ _ _ -> do
603 writeHandle handle htype
604 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
606 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
608 writeHandle handle (markHandle htype)
612 constructErrorAndFail "hSeek"
615 whence = case mode of
616 AbsoluteSeek -> ``SEEK_SET''
617 RelativeSeek -> ``SEEK_CUR''
618 SeekFromEnd -> ``SEEK_END''
621 %*********************************************************
623 \subsection[Query]{Handle Properties}
625 %*********************************************************
627 A number of operations return information about the properties of a
628 handle. Each of these operations returns $True$ if the
629 handle has the specified property, and $False$
632 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
633 {\em hdl} is not block-buffered. Otherwise it returns
634 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
635 $( Just n )$ for block-buffering of {\em n} bytes.
638 hIsOpen :: Handle -> IO Bool
640 htype <- readHandle handle
642 ErrorHandle ioError -> do
643 writeHandle handle htype
646 writeHandle handle htype
648 SemiClosedHandle _ _ -> do
649 writeHandle handle htype
652 writeHandle handle htype
655 hIsClosed :: Handle -> IO Bool
656 hIsClosed handle = do
657 htype <- readHandle handle
659 ErrorHandle ioError -> do
660 writeHandle handle htype
663 writeHandle handle htype
666 writeHandle handle htype
669 hIsReadable :: Handle -> IO Bool
670 hIsReadable handle = do
671 htype <- readHandle handle
673 ErrorHandle ioError -> do
674 writeHandle handle htype
677 writeHandle handle htype
678 ioe_closedHandle handle
679 SemiClosedHandle _ _ -> do
680 writeHandle handle htype
681 ioe_closedHandle handle
683 writeHandle handle htype
684 return (isReadable other)
686 isReadable (ReadHandle _ _ _) = True
687 isReadable (ReadWriteHandle _ _ _) = True
690 hIsWritable :: Handle -> IO Bool
691 hIsWritable handle = do
692 htype <- readHandle handle
694 ErrorHandle ioError -> do
695 writeHandle handle htype
698 writeHandle handle htype
699 ioe_closedHandle handle
700 SemiClosedHandle _ _ -> do
701 writeHandle handle htype
702 ioe_closedHandle handle
704 writeHandle handle htype
705 return (isWritable other)
707 isWritable (AppendHandle _ _ _) = True
708 isWritable (WriteHandle _ _ _) = True
709 isWritable (ReadWriteHandle _ _ _) = True
712 getBufferMode :: Handle__ -> IO Handle__
713 getBufferMode htype =
714 case bufferMode htype of
715 Just x -> return htype
717 rc <- _ccall_ getBufferMode (filePtr htype)
721 0 -> Just NoBuffering
722 -1 -> Just LineBuffering
723 -2 -> Just (BlockBuffering Nothing)
725 n -> Just (BlockBuffering (Just n))
726 return (case htype of
727 ReadHandle fp _ b -> ReadHandle fp mode b
728 WriteHandle fp _ b -> WriteHandle fp mode b
729 AppendHandle fp _ b -> AppendHandle fp mode b
730 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
732 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
733 hIsBlockBuffered handle = do
734 htype <- readHandle handle
736 ErrorHandle ioError -> do
737 writeHandle handle htype
740 writeHandle handle htype
741 ioe_closedHandle handle
742 SemiClosedHandle _ _ -> do
743 writeHandle handle htype
744 ioe_closedHandle handle
746 other <- getBufferMode other
747 case bufferMode other of
748 Just (BlockBuffering size) -> do
749 writeHandle handle other
752 writeHandle handle other
753 return (False, Nothing)
755 constructErrorAndFail "hIsBlockBuffered"
757 hIsLineBuffered :: Handle -> IO Bool
758 hIsLineBuffered handle = do
759 htype <- readHandle handle
761 ErrorHandle ioError -> do
762 writeHandle handle htype
765 writeHandle handle htype
766 ioe_closedHandle handle
767 SemiClosedHandle _ _ -> do
768 writeHandle handle htype
769 ioe_closedHandle handle
771 other <- getBufferMode other
772 case bufferMode other of
773 Just LineBuffering -> do
774 writeHandle handle other
777 writeHandle handle other
780 constructErrorAndFail "hIsLineBuffered"
782 hIsNotBuffered :: Handle -> IO Bool
783 hIsNotBuffered handle = do
784 htype <- readHandle handle
786 ErrorHandle ioError -> do
787 writeHandle handle htype
790 writeHandle handle htype
791 ioe_closedHandle handle
792 SemiClosedHandle _ _ -> do
793 writeHandle handle htype
794 ioe_closedHandle handle
796 other <- getBufferMode other
797 case bufferMode other of
798 Just NoBuffering -> do
799 writeHandle handle other
802 writeHandle handle other
805 constructErrorAndFail "hIsNotBuffered"
807 hGetBuffering :: Handle -> IO BufferMode
808 hGetBuffering handle = do
809 htype <- readHandle handle
811 ErrorHandle ioError -> do
812 writeHandle handle htype
815 writeHandle handle htype
816 ioe_closedHandle handle
817 SemiClosedHandle _ _ -> do
818 writeHandle handle htype
819 ioe_closedHandle handle
821 other <- getBufferMode other
822 case bufferMode other of
824 writeHandle handle other
827 constructErrorAndFail "hGetBuffering"
829 hIsSeekable :: Handle -> IO Bool
830 hIsSeekable handle = do
831 htype <- readHandle handle
833 ErrorHandle ioError -> do
834 writeHandle handle htype
837 writeHandle handle htype
838 ioe_closedHandle handle
839 SemiClosedHandle _ _ -> do
840 writeHandle handle htype
841 ioe_closedHandle handle
842 AppendHandle _ _ _ -> do
843 writeHandle handle htype
846 rc <- _ccall_ seekFileP (filePtr other)
847 writeHandle handle htype
851 _ -> constructErrorAndFail "hIsSeekable"
855 %*********************************************************
857 \subsection{Miscellaneous}
859 %*********************************************************
861 These two functions are meant to get things out of @IOErrors@. They don't!
864 ioeGetFileName :: IOError -> Maybe FilePath
865 ioeGetErrorString :: IOError -> String
866 ioeGetHandle :: IOError -> Maybe Handle
868 ioeGetHandle (IOError h _ _) = h
869 ioeGetErrorString (IOError _ iot str) =
874 ioeGetFileName (IOError _ _ str) =
875 case span (/=':') str of
881 Internal function for creating an @IOError@ representing the
882 access of a closed file.
886 ioe_closedHandle :: Handle -> IO a
887 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")