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 )
31 #ifndef __PARALLEL_HASKELL__
32 import Foreign ( ForeignObj, makeForeignObj, writeForeignObj )
35 #if defined(__CONCURRENT_HASKELL__)
41 %*********************************************************
43 \subsection{Types @FilePath@, @Handle@, @Handle__@}
45 %*********************************************************
47 The @Handle@ and @Handle__@ types are defined in @IOBase@.
50 type FilePath = String
52 {-# INLINE newHandle #-}
53 {-# INLINE readHandle #-}
54 {-# INLINE writeHandle #-}
55 newHandle :: Handle__ -> IO Handle
56 readHandle :: Handle -> IO Handle__
57 writeHandle :: Handle -> Handle__ -> IO ()
59 #if defined(__CONCURRENT_HASKELL__)
64 newHandle v = stToIO (newVar v)
65 readHandle h = stToIO (readVar h)
66 writeHandle h v = stToIO (writeVar h v)
71 %*********************************************************
73 \subsection{Functions}
75 %*********************************************************
78 #ifndef __PARALLEL_HASKELL__
79 filePtr :: Handle__ -> ForeignObj
81 filePtr :: Handle__ -> Addr
83 filePtr (SemiClosedHandle fp _) = fp
84 filePtr (ReadHandle fp _ _) = fp
85 filePtr (WriteHandle fp _ _) = fp
86 filePtr (AppendHandle fp _ _) = fp
87 filePtr (ReadWriteHandle fp _ _) = fp
89 bufferMode :: Handle__ -> Maybe BufferMode
90 bufferMode (ReadHandle _ m _) = m
91 bufferMode (WriteHandle _ m _) = m
92 bufferMode (AppendHandle _ m _) = m
93 bufferMode (ReadWriteHandle _ m _) = m
95 markHandle :: Handle__ -> Handle__
96 markHandle h@(ReadHandle fp m b)
98 | otherwise = ReadHandle fp m True
99 markHandle h@(WriteHandle fp m b)
101 | otherwise = WriteHandle fp m True
102 markHandle h@(AppendHandle fp m b)
104 | otherwise = AppendHandle fp m True
105 markHandle h@(ReadWriteHandle fp m b)
107 | otherwise = ReadWriteHandle fp m True
110 -------------------------------------------
112 %*********************************************************
114 \subsection[StdHandles]{Standard handles}
116 %*********************************************************
118 Three handles are allocated during program initialisation. The first
119 two manage input or output from the Haskell program's standard input
120 or output channel respectively. The third manages output to the
121 standard error channel. These handles are initially open.
124 stdin, stdout, stderr :: Handle
126 stdin = unsafePerformIO (do
127 rc <- _ccall_ getLock (``stdin''::Addr) 0
129 0 -> newHandle ClosedHandle
131 #ifndef __PARALLEL_HASKELL__
132 fp <- makeForeignObj (``stdin''::Addr) (``&freeStdFile''::Addr)
133 newHandle (ReadHandle fp Nothing False)
135 newHandle (ReadHandle ``stdin'' Nothing False)
137 _ -> do ioError <- constructError "stdin"
138 newHandle (ErrorHandle ioError)
141 stdout = unsafePerformIO (do
142 rc <- _ccall_ getLock (``stdout''::Addr) 1
144 0 -> newHandle ClosedHandle
146 #ifndef __PARALLEL_HASKELL__
147 fp <- makeForeignObj (``stdout''::Addr) (``&freeStdFile''::Addr)
148 newHandle (WriteHandle fp Nothing False)
150 newHandle (WriteHandle ``stdout'' Nothing False)
152 _ -> do ioError <- constructError "stdout"
153 newHandle (ErrorHandle ioError)
156 stderr = unsafePerformIO (do
157 rc <- _ccall_ getLock (``stderr''::Addr) 1
159 0 -> newHandle ClosedHandle
161 #ifndef __PARALLEL_HASKELL__
162 fp <- makeForeignObj (``stderr''::Addr) (``&freeStdFile''::Addr)
163 newHandle (WriteHandle fp (Just NoBuffering) False)
165 newHandle (WriteHandle ``stderr'' (Just NoBuffering) False)
167 _ -> do ioError <- constructError "stderr"
168 newHandle (ErrorHandle ioError)
172 %*********************************************************
174 \subsection[OpeningClosing]{Opening and Closing Files}
176 %*********************************************************
179 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
180 deriving (Eq, Ord, Ix, Enum, Read, Show)
182 openFile :: FilePath -> IOMode -> IO Handle
185 ptr <- _ccall_ openFile f m'
186 if ptr /= ``NULL'' then do
187 #ifndef __PARALLEL_HASKELL__
188 fp <- makeForeignObj ptr ((``&freeFile'')::Addr)
189 newHandle (htype fp Nothing False)
191 newHandle (htype ptr Nothing False)
194 ioError@(IOError hn iot msg) <- constructError "openFile"
196 improved_error -- a HACK, I guess
198 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
199 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
200 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
208 ReadWriteMode -> "r+"
211 ReadMode -> ReadHandle
212 WriteMode -> WriteHandle
213 AppendMode -> AppendHandle
214 ReadWriteMode -> ReadWriteHandle
217 Computation $openFile file mode$ allocates and returns a new, open
218 handle to manage the file {\em file}. It manages input if {\em mode}
219 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
220 and both input and output if mode is $ReadWriteMode$.
222 If the file does not exist and it is opened for output, it should be
223 created as a new file. If {\em mode} is $WriteMode$ and the file
224 already exists, then it should be truncated to zero length. The
225 handle is positioned at the end of the file if {\em mode} is
226 $AppendMode$, and otherwise at the beginning (in which case its
227 internal position is 0).
229 Implementations should enforce, locally to the Haskell process,
230 multiple-reader single-writer locking on files, which is to say that
231 there may either be many handles on the same file which manage input,
232 or just one handle on the file which manages output. If any open or
233 semi-closed handle is managing a file for output, no new handle can be
234 allocated for that file. If any open or semi-closed handle is
235 managing a file for input, new handles can only be allocated if they
236 do not manage output.
238 Two files are the same if they have the same absolute name. An
239 implementation is free to impose stricter conditions.
242 hClose :: Handle -> IO ()
245 htype <- readHandle handle
247 ErrorHandle ioError -> do
248 writeHandle handle htype
251 writeHandle handle htype
252 ioe_closedHandle handle
253 SemiClosedHandle fp (buf,_) -> do
254 (if buf /= ``NULL'' then
258 fp_a <- _casm_ `` %r = (char *)%0; '' fp
259 if fp_a /= (``NULL''::Addr) then do
260 -- Under what condition can this be NULL?
261 rc <- _ccall_ closeFile fp
262 {- We explicitly close a file object so that we can be told
263 if there were any errors. Note that after @hClose@
264 has been performed, the ForeignObj embedded in the Handle
265 is still lying around in the heap, so care is taken
266 to avoid closing the file object when the ForeignObj
269 #ifndef __PARALLEL_HASKELL__
270 -- Mark the foreign object data value as
271 -- gone to the finaliser (freeFile())
272 writeForeignObj fp ``NULL''
274 writeHandle handle ClosedHandle
276 writeHandle handle htype
277 constructErrorAndFail "hClose"
279 else writeHandle handle htype
282 let fp = filePtr other
283 rc <- _ccall_ closeFile fp
285 #ifndef __PARALLEL_HASKELL__
286 -- Mark the foreign object data
287 writeForeignObj fp ``NULL''
289 writeHandle handle ClosedHandle
291 writeHandle handle htype
292 constructErrorAndFail "hClose"
295 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
296 computation finishes, any items buffered for output and not already
297 sent to the operating system are flushed as for $flush$.
299 %*********************************************************
301 \subsection[EOF]{Detecting the End of Input}
303 %*********************************************************
306 For a handle {\em hdl} which attached to a physical file, $hFileSize
307 hdl$ returns the size of {\em hdl} in terms of the number of items
308 which can be read from {\em hdl}.
311 hFileSize :: Handle -> IO Integer
312 hFileSize handle = do
313 htype <- readHandle handle
315 ErrorHandle ioError -> do
316 writeHandle handle htype
319 writeHandle handle htype
320 ioe_closedHandle handle
321 SemiClosedHandle _ _ -> do
322 writeHandle handle htype
323 ioe_closedHandle handle
325 -- HACK! We build a unique MP_INT of the right shape to hold
326 -- a single unsigned word, and we let the C routine
327 -- change the data bits
329 -- For some reason, this fails to typecheck if converted to a do
331 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
332 case int2Integer# hack# of
333 result@(J# _ _ d#) -> do
334 let bogus_bounds = (error "fileSize"::(Int,Int))
335 rc <- _ccall_ fileSize (filePtr other)
336 (ByteArray bogus_bounds d#)
337 writeHandle handle htype
341 constructErrorAndFail "hFileSize"
344 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
345 $True$ if no further input can be taken from {\em hdl} or for a
346 physical file, if the current I/O position is equal to the length of
347 the file. Otherwise, it returns $False$.
350 hIsEOF :: Handle -> IO Bool
352 htype <- readHandle handle
354 ErrorHandle ioError -> do
355 writeHandle handle htype
358 writeHandle handle htype
359 ioe_closedHandle handle
360 SemiClosedHandle _ _ -> do
361 writeHandle handle htype
362 ioe_closedHandle handle
363 WriteHandle _ _ _ -> do
364 writeHandle handle htype
365 fail (IOError (Just handle) IllegalOperation
366 "handle is not open for reading")
367 AppendHandle _ _ _ -> do
368 writeHandle handle htype
369 fail (IOError (Just handle) IllegalOperation
370 "handle is not open for reading")
372 rc <- _ccall_ fileEOF (filePtr other)
373 writeHandle handle (markHandle htype)
377 _ -> constructErrorAndFail "hIsEOF"
383 %*********************************************************
385 \subsection[Buffering]{Buffering Operations}
387 %*********************************************************
389 Three kinds of buffering are supported: line-buffering,
390 block-buffering or no-buffering. See @IOBase@ for definition
391 and further explanation of what the type represent.
393 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
394 handle {\em hdl} on subsequent reads and writes.
398 If {\em mode} is @LineBuffering@, line-buffering should be
401 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
402 should be enabled if possible. The size of the buffer is {\em n} items
403 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
405 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
408 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
409 to @NoBuffering@, then any items in the output buffer are written to
410 the device, and any items in the input buffer are discarded. The
411 default buffering mode when a handle is opened is
412 implementation-dependent and may depend on the object which is
413 attached to that handle.
416 hSetBuffering :: Handle -> BufferMode -> IO ()
418 hSetBuffering handle mode =
420 BlockBuffering (Just n)
421 | n <= 0 -> fail (IOError (Just handle) InvalidArgument
422 "illegal buffer size")
424 htype <- readHandle handle
425 if isMarked htype then do
426 writeHandle handle htype
427 fail (IOError (Just handle)
429 "can't set buffering for a dirty handle")
432 ErrorHandle ioError -> do
433 writeHandle handle htype
436 writeHandle handle htype
437 ioe_closedHandle handle
438 SemiClosedHandle _ _ -> do
439 writeHandle handle htype
440 ioe_closedHandle handle
442 rc <- _ccall_ setBuffering (filePtr other) bsize
444 writeHandle handle ((hcon other) (filePtr other)
447 writeHandle handle htype
448 constructErrorAndFail "hSetBuffering"
451 isMarked :: Handle__ -> Bool
452 isMarked (ReadHandle fp m b) = b
453 isMarked (WriteHandle fp m b) = b
454 isMarked (AppendHandle fp m b) = b
455 isMarked (ReadWriteHandle fp m b) = b
461 BlockBuffering Nothing -> -2
462 BlockBuffering (Just n) -> n
464 #ifndef __PARALLEL_HASKELL__
465 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
467 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
469 hcon (ReadHandle _ _ _) = ReadHandle
470 hcon (WriteHandle _ _ _) = WriteHandle
471 hcon (AppendHandle _ _ _) = AppendHandle
472 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
475 Computation $flush hdl$ causes any items buffered for output in handle
476 {\em hdl} to be sent immediately to the operating system.
479 hFlush :: Handle -> IO ()
481 htype <- readHandle handle
483 ErrorHandle ioError -> do
484 writeHandle handle htype
487 writeHandle handle htype
488 ioe_closedHandle handle
489 SemiClosedHandle _ _ -> do
490 writeHandle handle htype
491 ioe_closedHandle handle
493 rc <- _ccall_ flushFile (filePtr other)
494 writeHandle handle (markHandle htype)
498 constructErrorAndFail "hFlush"
502 %*********************************************************
504 \subsection[Seeking]{Repositioning Handles}
506 %*********************************************************
509 data HandlePosn = HandlePosn Handle Int
511 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
512 deriving (Eq, Ord, Ix, Enum, Read, Show)
515 Computation $hGetPosn hdl$ returns the current I/O
516 position of {\em hdl} as an abstract position. Computation
517 $hSetPosn p$ sets the position of {\em hdl}
518 to a previously obtained position {\em p}.
521 hGetPosn :: Handle -> IO HandlePosn
523 htype <- readHandle handle
525 ErrorHandle ioError -> do
526 writeHandle handle htype
529 writeHandle handle htype
530 ioe_closedHandle handle
531 SemiClosedHandle _ _ -> do
532 writeHandle handle htype
533 ioe_closedHandle handle
535 posn <- _ccall_ getFilePosn (filePtr other)
536 writeHandle handle htype
538 return (HandlePosn handle posn)
540 constructErrorAndFail "hGetPosn"
542 hSetPosn :: HandlePosn -> IO ()
543 hSetPosn (HandlePosn handle posn) = do
544 htype <- readHandle handle
546 ErrorHandle ioError -> do
547 writeHandle handle htype
550 writeHandle handle htype
551 ioe_closedHandle handle
552 SemiClosedHandle _ _ -> do
553 writeHandle handle htype
554 ioe_closedHandle handle
555 AppendHandle _ _ _ -> do
556 writeHandle handle htype
557 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
559 rc <- _ccall_ setFilePosn (filePtr other) posn
560 writeHandle handle (markHandle htype)
564 constructErrorAndFail "hSetPosn"
567 Computation $hSeek hdl mode i$ sets the position of handle
568 {\em hdl} depending on $mode$. If {\em mode} is
570 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
571 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
572 the current position.
573 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
575 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
576 the beginning of the file.
579 Some handles may not be seekable $hIsSeekable$, or only support a
580 subset of the possible positioning operations (e.g. it may only be
581 possible to seek to the end of a tape, or to a positive offset from
582 the beginning or current position).
584 It is not possible to set a negative I/O position, or for a physical
585 file, an I/O position beyond the current end-of-file.
588 hSeek :: Handle -> SeekMode -> Integer -> IO ()
589 hSeek handle mode offset@(J# _ s# d#) = do
590 htype <- readHandle handle
592 ErrorHandle ioError -> do
593 writeHandle handle htype
596 writeHandle handle htype
597 ioe_closedHandle handle
598 SemiClosedHandle _ _ -> do
599 writeHandle handle htype
600 ioe_closedHandle handle
601 AppendHandle _ _ _ -> do
602 writeHandle handle htype
603 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
605 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
607 writeHandle handle (markHandle htype)
611 constructErrorAndFail "hSeek"
614 whence = case mode of
615 AbsoluteSeek -> ``SEEK_SET''
616 RelativeSeek -> ``SEEK_CUR''
617 SeekFromEnd -> ``SEEK_END''
620 %*********************************************************
622 \subsection[Query]{Handle Properties}
624 %*********************************************************
626 A number of operations return information about the properties of a
627 handle. Each of these operations returns $True$ if the
628 handle has the specified property, and $False$
631 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
632 {\em hdl} is not block-buffered. Otherwise it returns
633 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
634 $( Just n )$ for block-buffering of {\em n} bytes.
637 hIsOpen :: Handle -> IO Bool
639 htype <- readHandle handle
641 ErrorHandle ioError -> do
642 writeHandle handle htype
645 writeHandle handle htype
647 SemiClosedHandle _ _ -> do
648 writeHandle handle htype
651 writeHandle handle htype
654 hIsClosed :: Handle -> IO Bool
655 hIsClosed handle = do
656 htype <- readHandle handle
658 ErrorHandle ioError -> do
659 writeHandle handle htype
662 writeHandle handle htype
665 writeHandle handle htype
668 hIsReadable :: Handle -> IO Bool
669 hIsReadable handle = do
670 htype <- readHandle handle
672 ErrorHandle ioError -> do
673 writeHandle handle htype
676 writeHandle handle htype
677 ioe_closedHandle handle
678 SemiClosedHandle _ _ -> do
679 writeHandle handle htype
680 ioe_closedHandle handle
682 writeHandle handle htype
683 return (isReadable other)
685 isReadable (ReadHandle _ _ _) = True
686 isReadable (ReadWriteHandle _ _ _) = True
689 hIsWritable :: Handle -> IO Bool
690 hIsWritable handle = do
691 htype <- readHandle handle
693 ErrorHandle ioError -> do
694 writeHandle handle htype
697 writeHandle handle htype
698 ioe_closedHandle handle
699 SemiClosedHandle _ _ -> do
700 writeHandle handle htype
701 ioe_closedHandle handle
703 writeHandle handle htype
704 return (isWritable other)
706 isWritable (AppendHandle _ _ _) = True
707 isWritable (WriteHandle _ _ _) = True
708 isWritable (ReadWriteHandle _ _ _) = True
711 getBufferMode :: Handle__ -> IO Handle__
712 getBufferMode htype =
713 case bufferMode htype of
714 Just x -> return htype
716 rc <- _ccall_ getBufferMode (filePtr htype)
720 0 -> Just NoBuffering
721 -1 -> Just LineBuffering
722 -2 -> Just (BlockBuffering Nothing)
724 n -> Just (BlockBuffering (Just n))
725 return (case htype of
726 ReadHandle fp _ b -> ReadHandle fp mode b
727 WriteHandle fp _ b -> WriteHandle fp mode b
728 AppendHandle fp _ b -> AppendHandle fp mode b
729 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
731 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
732 hIsBlockBuffered handle = do
733 htype <- readHandle handle
735 ErrorHandle ioError -> do
736 writeHandle handle htype
739 writeHandle handle htype
740 ioe_closedHandle handle
741 SemiClosedHandle _ _ -> do
742 writeHandle handle htype
743 ioe_closedHandle handle
745 other <- getBufferMode other
746 case bufferMode other of
747 Just (BlockBuffering size) -> do
748 writeHandle handle other
751 writeHandle handle other
752 return (False, Nothing)
754 constructErrorAndFail "hIsBlockBuffered"
756 hIsLineBuffered :: Handle -> IO Bool
757 hIsLineBuffered 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 LineBuffering -> do
773 writeHandle handle other
776 writeHandle handle other
779 constructErrorAndFail "hIsLineBuffered"
781 hIsNotBuffered :: Handle -> IO Bool
782 hIsNotBuffered 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 NoBuffering -> do
798 writeHandle handle other
801 writeHandle handle other
804 constructErrorAndFail "hIsNotBuffered"
806 hGetBuffering :: Handle -> IO BufferMode
807 hGetBuffering 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
823 writeHandle handle other
826 constructErrorAndFail "hGetBuffering"
828 hIsSeekable :: Handle -> IO Bool
829 hIsSeekable handle = do
830 htype <- readHandle handle
832 ErrorHandle ioError -> do
833 writeHandle handle htype
836 writeHandle handle htype
837 ioe_closedHandle handle
838 SemiClosedHandle _ _ -> do
839 writeHandle handle htype
840 ioe_closedHandle handle
841 AppendHandle _ _ _ -> do
842 writeHandle handle htype
845 rc <- _ccall_ seekFileP (filePtr other)
846 writeHandle handle htype
850 _ -> constructErrorAndFail "hIsSeekable"
854 %*********************************************************
856 \subsection{Miscellaneous}
858 %*********************************************************
860 These two functions are meant to get things out of @IOErrors@. They don't!
863 ioeGetFileName :: IOError -> Maybe FilePath
864 ioeGetErrorString :: IOError -> String
865 ioeGetHandle :: IOError -> Maybe Handle
867 ioeGetHandle (IOError h _ _) = h
868 ioeGetErrorString (IOError _ iot str) =
873 ioeGetFileName (IOError _ _ str) =
874 case span (/=':') str of
880 Internal function for creating an @IOError@ representing the
881 access of a closed file.
885 ioe_closedHandle :: Handle -> IO a
886 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")