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)
189 openFile :: FilePath -> IOMode -> IO Handle
192 ptr <- _ccall_ openFile f m'
193 if ptr /= ``NULL'' then do
194 #ifndef __PARALLEL_HASKELL__
195 fp <- makeForeignObj ptr ((``&freeFile'')::Addr)
196 newHandle (htype fp Nothing False)
198 newHandle (htype ptr Nothing False)
201 ioError@(IOError hn iot msg) <- constructError "openFile"
203 improved_error -- a HACK, I guess
205 AlreadyExists -> IOError hn AlreadyExists (msg ++ ": " ++ f)
206 NoSuchThing -> IOError hn NoSuchThing (msg ++ ": " ++ f)
207 PermissionDenied -> IOError hn PermissionDenied (msg ++ ": " ++ f)
215 ReadWriteMode -> "r+"
218 ReadMode -> ReadHandle
219 WriteMode -> WriteHandle
220 AppendMode -> AppendHandle
221 ReadWriteMode -> ReadWriteHandle
224 Computation $openFile file mode$ allocates and returns a new, open
225 handle to manage the file {\em file}. It manages input if {\em mode}
226 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
227 and both input and output if mode is $ReadWriteMode$.
229 If the file does not exist and it is opened for output, it should be
230 created as a new file. If {\em mode} is $WriteMode$ and the file
231 already exists, then it should be truncated to zero length. The
232 handle is positioned at the end of the file if {\em mode} is
233 $AppendMode$, and otherwise at the beginning (in which case its
234 internal position is 0).
236 Implementations should enforce, locally to the Haskell process,
237 multiple-reader single-writer locking on files, which is to say that
238 there may either be many handles on the same file which manage input,
239 or just one handle on the file which manages output. If any open or
240 semi-closed handle is managing a file for output, no new handle can be
241 allocated for that file. If any open or semi-closed handle is
242 managing a file for input, new handles can only be allocated if they
243 do not manage output.
245 Two files are the same if they have the same absolute name. An
246 implementation is free to impose stricter conditions.
249 hClose :: Handle -> IO ()
252 htype <- readHandle handle
254 ErrorHandle ioError -> do
255 writeHandle handle htype
258 writeHandle handle htype
259 ioe_closedHandle handle
260 SemiClosedHandle fp (buf,_) -> do
261 (if buf /= ``NULL'' then
265 fp_a <- _casm_ `` %r = (char *)%0; '' fp
266 if fp_a /= (``NULL''::Addr) then do
267 -- Under what condition can this be NULL?
268 rc <- _ccall_ closeFile fp
269 {- We explicitly close a file object so that we can be told
270 if there were any errors. Note that after @hClose@
271 has been performed, the ForeignObj embedded in the Handle
272 is still lying around in the heap, so care is taken
273 to avoid closing the file object when the ForeignObj
276 #ifndef __PARALLEL_HASKELL__
277 -- Mark the foreign object data value as
278 -- gone to the finaliser (freeFile())
279 writeForeignObj fp ``NULL''
281 writeHandle handle ClosedHandle
283 writeHandle handle htype
284 constructErrorAndFail "hClose"
286 else writeHandle handle htype
289 let fp = filePtr other
290 rc <- _ccall_ closeFile fp
292 #ifndef __PARALLEL_HASKELL__
293 -- Mark the foreign object data
294 writeForeignObj fp ``NULL''
296 writeHandle handle ClosedHandle
298 writeHandle handle htype
299 constructErrorAndFail "hClose"
302 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
303 computation finishes, any items buffered for output and not already
304 sent to the operating system are flushed as for $flush$.
306 %*********************************************************
308 \subsection[EOF]{Detecting the End of Input}
310 %*********************************************************
313 For a handle {\em hdl} which attached to a physical file, $hFileSize
314 hdl$ returns the size of {\em hdl} in terms of the number of items
315 which can be read from {\em hdl}.
318 hFileSize :: Handle -> IO Integer
319 hFileSize handle = do
320 htype <- readHandle handle
322 ErrorHandle ioError -> do
323 writeHandle handle htype
326 writeHandle handle htype
327 ioe_closedHandle handle
328 SemiClosedHandle _ _ -> do
329 writeHandle handle htype
330 ioe_closedHandle handle
332 -- HACK! We build a unique MP_INT of the right shape to hold
333 -- a single unsigned word, and we let the C routine
334 -- change the data bits
336 -- For some reason, this fails to typecheck if converted to a do
338 _casm_ ``%r = 1;'' >>= \(I# hack#) ->
339 case int2Integer# hack# of
340 result@(J# _ _ d#) -> do
341 let bogus_bounds = (error "fileSize"::(Int,Int))
342 rc <- _ccall_ fileSize (filePtr other)
343 (ByteArray bogus_bounds d#)
344 writeHandle handle htype
348 constructErrorAndFail "hFileSize"
351 For a readable handle {\em hdl}, computation $hIsEOF hdl$ returns
352 $True$ if no further input can be taken from {\em hdl} or for a
353 physical file, if the current I/O position is equal to the length of
354 the file. Otherwise, it returns $False$.
357 hIsEOF :: Handle -> IO Bool
359 htype <- readHandle handle
361 ErrorHandle ioError -> do
362 writeHandle handle htype
365 writeHandle handle htype
366 ioe_closedHandle handle
367 SemiClosedHandle _ _ -> do
368 writeHandle handle htype
369 ioe_closedHandle handle
370 WriteHandle _ _ _ -> do
371 writeHandle handle htype
372 fail (IOError (Just handle) IllegalOperation
373 "handle is not open for reading")
374 AppendHandle _ _ _ -> do
375 writeHandle handle htype
376 fail (IOError (Just handle) IllegalOperation
377 "handle is not open for reading")
379 rc <- _ccall_ fileEOF (filePtr other)
380 writeHandle handle (markHandle htype)
384 _ -> constructErrorAndFail "hIsEOF"
390 %*********************************************************
392 \subsection[Buffering]{Buffering Operations}
394 %*********************************************************
396 Three kinds of buffering are supported: line-buffering,
397 block-buffering or no-buffering. See @IOBase@ for definition
398 and further explanation of what the type represent.
400 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
401 handle {\em hdl} on subsequent reads and writes.
405 If {\em mode} is @LineBuffering@, line-buffering should be
408 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
409 should be enabled if possible. The size of the buffer is {\em n} items
410 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
412 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
415 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
416 to @NoBuffering@, then any items in the output buffer are written to
417 the device, and any items in the input buffer are discarded. The
418 default buffering mode when a handle is opened is
419 implementation-dependent and may depend on the object which is
420 attached to that handle.
423 hSetBuffering :: Handle -> BufferMode -> IO ()
425 hSetBuffering handle mode =
427 BlockBuffering (Just n)
428 | n <= 0 -> fail (IOError (Just handle) InvalidArgument
429 "illegal buffer size")
431 htype <- readHandle handle
432 if isMarked htype then do
433 writeHandle handle htype
434 fail (IOError (Just handle)
436 "can't set buffering for a dirty handle")
439 ErrorHandle ioError -> do
440 writeHandle handle htype
443 writeHandle handle htype
444 ioe_closedHandle handle
445 SemiClosedHandle _ _ -> do
446 writeHandle handle htype
447 ioe_closedHandle handle
449 rc <- _ccall_ setBuffering (filePtr other) bsize
451 writeHandle handle ((hcon other) (filePtr other)
454 writeHandle handle htype
455 constructErrorAndFail "hSetBuffering"
458 isMarked :: Handle__ -> Bool
459 isMarked (ReadHandle fp m b) = b
460 isMarked (WriteHandle fp m b) = b
461 isMarked (AppendHandle fp m b) = b
462 isMarked (ReadWriteHandle fp m b) = b
468 BlockBuffering Nothing -> -2
469 BlockBuffering (Just n) -> n
471 #ifndef __PARALLEL_HASKELL__
472 hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
474 hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
476 hcon (ReadHandle _ _ _) = ReadHandle
477 hcon (WriteHandle _ _ _) = WriteHandle
478 hcon (AppendHandle _ _ _) = AppendHandle
479 hcon (ReadWriteHandle _ _ _) = ReadWriteHandle
482 Computation $flush hdl$ causes any items buffered for output in handle
483 {\em hdl} to be sent immediately to the operating system.
486 hFlush :: Handle -> IO ()
488 htype <- readHandle handle
490 ErrorHandle ioError -> do
491 writeHandle handle htype
494 writeHandle handle htype
495 ioe_closedHandle handle
496 SemiClosedHandle _ _ -> do
497 writeHandle handle htype
498 ioe_closedHandle handle
500 rc <- _ccall_ flushFile (filePtr other)
501 writeHandle handle (markHandle htype)
505 constructErrorAndFail "hFlush"
509 %*********************************************************
511 \subsection[Seeking]{Repositioning Handles}
513 %*********************************************************
516 data HandlePosn = HandlePosn Handle Int
518 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
519 deriving (Eq, Ord, Ix, Enum, Read, Show)
522 Computation $hGetPosn hdl$ returns the current I/O
523 position of {\em hdl} as an abstract position. Computation
524 $hSetPosn p$ sets the position of {\em hdl}
525 to a previously obtained position {\em p}.
528 hGetPosn :: Handle -> IO HandlePosn
530 htype <- readHandle handle
532 ErrorHandle ioError -> do
533 writeHandle handle htype
536 writeHandle handle htype
537 ioe_closedHandle handle
538 SemiClosedHandle _ _ -> do
539 writeHandle handle htype
540 ioe_closedHandle handle
542 posn <- _ccall_ getFilePosn (filePtr other)
543 writeHandle handle htype
545 return (HandlePosn handle posn)
547 constructErrorAndFail "hGetPosn"
549 hSetPosn :: HandlePosn -> IO ()
550 hSetPosn (HandlePosn handle posn) = do
551 htype <- readHandle handle
553 ErrorHandle ioError -> do
554 writeHandle handle htype
557 writeHandle handle htype
558 ioe_closedHandle handle
559 SemiClosedHandle _ _ -> do
560 writeHandle handle htype
561 ioe_closedHandle handle
562 AppendHandle _ _ _ -> do
563 writeHandle handle htype
564 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
566 rc <- _ccall_ setFilePosn (filePtr other) posn
567 writeHandle handle (markHandle htype)
571 constructErrorAndFail "hSetPosn"
574 Computation $hSeek hdl mode i$ sets the position of handle
575 {\em hdl} depending on $mode$. If {\em mode} is
577 \item[{\bf AbsoluteSeek}] The position of {\em hdl} is set to {\em i}.
578 \item[{\bf RelativeSeek}] The position of {\em hdl} is set to offset {\em i} from
579 the current position.
580 \item[{\bf SeekToEnd}] The position of {\em hdl} is set to offset {\em i} from
582 \item[{\bf SeekFromBeginning}] The position of {\em hdl} is set to offset {\em i} from
583 the beginning of the file.
586 Some handles may not be seekable $hIsSeekable$, or only support a
587 subset of the possible positioning operations (e.g. it may only be
588 possible to seek to the end of a tape, or to a positive offset from
589 the beginning or current position).
591 It is not possible to set a negative I/O position, or for a physical
592 file, an I/O position beyond the current end-of-file.
595 hSeek :: Handle -> SeekMode -> Integer -> IO ()
596 hSeek handle mode offset@(J# _ s# d#) = do
597 htype <- readHandle handle
599 ErrorHandle ioError -> do
600 writeHandle handle htype
603 writeHandle handle htype
604 ioe_closedHandle handle
605 SemiClosedHandle _ _ -> do
606 writeHandle handle htype
607 ioe_closedHandle handle
608 AppendHandle _ _ _ -> do
609 writeHandle handle htype
610 fail (IOError (Just handle) IllegalOperation "handle is not seekable")
612 rc <- _ccall_ seekFile (filePtr other) whence (I# s#)
614 writeHandle handle (markHandle htype)
618 constructErrorAndFail "hSeek"
621 whence = case mode of
622 AbsoluteSeek -> ``SEEK_SET''
623 RelativeSeek -> ``SEEK_CUR''
624 SeekFromEnd -> ``SEEK_END''
627 %*********************************************************
629 \subsection[Query]{Handle Properties}
631 %*********************************************************
633 A number of operations return information about the properties of a
634 handle. Each of these operations returns $True$ if the
635 handle has the specified property, and $False$
638 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
639 {\em hdl} is not block-buffered. Otherwise it returns
640 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
641 $( Just n )$ for block-buffering of {\em n} bytes.
644 hIsOpen :: Handle -> IO Bool
646 htype <- readHandle handle
648 ErrorHandle ioError -> do
649 writeHandle handle htype
652 writeHandle handle htype
654 SemiClosedHandle _ _ -> do
655 writeHandle handle htype
658 writeHandle handle htype
661 hIsClosed :: Handle -> IO Bool
662 hIsClosed handle = do
663 htype <- readHandle handle
665 ErrorHandle ioError -> do
666 writeHandle handle htype
669 writeHandle handle htype
672 writeHandle handle htype
675 hIsReadable :: Handle -> IO Bool
676 hIsReadable handle = do
677 htype <- readHandle handle
679 ErrorHandle ioError -> do
680 writeHandle handle htype
683 writeHandle handle htype
684 ioe_closedHandle handle
685 SemiClosedHandle _ _ -> do
686 writeHandle handle htype
687 ioe_closedHandle handle
689 writeHandle handle htype
690 return (isReadable other)
692 isReadable (ReadHandle _ _ _) = True
693 isReadable (ReadWriteHandle _ _ _) = True
696 hIsWritable :: Handle -> IO Bool
697 hIsWritable handle = do
698 htype <- readHandle handle
700 ErrorHandle ioError -> do
701 writeHandle handle htype
704 writeHandle handle htype
705 ioe_closedHandle handle
706 SemiClosedHandle _ _ -> do
707 writeHandle handle htype
708 ioe_closedHandle handle
710 writeHandle handle htype
711 return (isWritable other)
713 isWritable (AppendHandle _ _ _) = True
714 isWritable (WriteHandle _ _ _) = True
715 isWritable (ReadWriteHandle _ _ _) = True
718 getBufferMode :: Handle__ -> IO Handle__
719 getBufferMode htype =
720 case bufferMode htype of
721 Just x -> return htype
723 rc <- _ccall_ getBufferMode (filePtr htype)
727 0 -> Just NoBuffering
728 -1 -> Just LineBuffering
729 -2 -> Just (BlockBuffering Nothing)
731 n -> Just (BlockBuffering (Just n))
732 return (case htype of
733 ReadHandle fp _ b -> ReadHandle fp mode b
734 WriteHandle fp _ b -> WriteHandle fp mode b
735 AppendHandle fp _ b -> AppendHandle fp mode b
736 ReadWriteHandle fp _ b -> ReadWriteHandle fp mode b)
738 hIsBlockBuffered :: Handle -> IO (Bool,Maybe Int)
739 hIsBlockBuffered handle = do
740 htype <- readHandle handle
742 ErrorHandle ioError -> do
743 writeHandle handle htype
746 writeHandle handle htype
747 ioe_closedHandle handle
748 SemiClosedHandle _ _ -> do
749 writeHandle handle htype
750 ioe_closedHandle handle
752 other <- getBufferMode other
753 case bufferMode other of
754 Just (BlockBuffering size) -> do
755 writeHandle handle other
758 writeHandle handle other
759 return (False, Nothing)
761 constructErrorAndFail "hIsBlockBuffered"
763 hIsLineBuffered :: Handle -> IO Bool
764 hIsLineBuffered handle = do
765 htype <- readHandle handle
767 ErrorHandle ioError -> do
768 writeHandle handle htype
771 writeHandle handle htype
772 ioe_closedHandle handle
773 SemiClosedHandle _ _ -> do
774 writeHandle handle htype
775 ioe_closedHandle handle
777 other <- getBufferMode other
778 case bufferMode other of
779 Just LineBuffering -> do
780 writeHandle handle other
783 writeHandle handle other
786 constructErrorAndFail "hIsLineBuffered"
788 hIsNotBuffered :: Handle -> IO Bool
789 hIsNotBuffered handle = do
790 htype <- readHandle handle
792 ErrorHandle ioError -> do
793 writeHandle handle htype
796 writeHandle handle htype
797 ioe_closedHandle handle
798 SemiClosedHandle _ _ -> do
799 writeHandle handle htype
800 ioe_closedHandle handle
802 other <- getBufferMode other
803 case bufferMode other of
804 Just NoBuffering -> do
805 writeHandle handle other
808 writeHandle handle other
811 constructErrorAndFail "hIsNotBuffered"
813 hGetBuffering :: Handle -> IO BufferMode
814 hGetBuffering handle = do
815 htype <- readHandle handle
817 ErrorHandle ioError -> do
818 writeHandle handle htype
821 writeHandle handle htype
822 ioe_closedHandle handle
823 SemiClosedHandle _ _ -> do
824 writeHandle handle htype
825 ioe_closedHandle handle
827 other <- getBufferMode other
828 case bufferMode other of
830 writeHandle handle other
833 constructErrorAndFail "hGetBuffering"
835 hIsSeekable :: Handle -> IO Bool
836 hIsSeekable handle = do
837 htype <- readHandle handle
839 ErrorHandle ioError -> do
840 writeHandle handle htype
843 writeHandle handle htype
844 ioe_closedHandle handle
845 SemiClosedHandle _ _ -> do
846 writeHandle handle htype
847 ioe_closedHandle handle
848 AppendHandle _ _ _ -> do
849 writeHandle handle htype
852 rc <- _ccall_ seekFileP (filePtr other)
853 writeHandle handle htype
857 _ -> constructErrorAndFail "hIsSeekable"
861 %*********************************************************
863 \subsection{Miscellaneous}
865 %*********************************************************
867 These two functions are meant to get things out of @IOErrors@. They don't!
870 ioeGetFileName :: IOError -> Maybe FilePath
871 ioeGetErrorString :: IOError -> String
872 ioeGetHandle :: IOError -> Maybe Handle
874 ioeGetHandle (IOError h _ _) = h
875 ioeGetErrorString (IOError _ iot str) =
880 ioeGetFileName (IOError _ _ str) =
881 case span (/=':') str of
887 Internal function for creating an @IOError@ representing the
888 access of a closed file.
892 ioe_closedHandle :: Handle -> IO a
893 ioe_closedHandle h = fail (IOError (Just h) IllegalOperation "handle is closed")