1 % ------------------------------------------------------------------------------
2 % $Id: PrelHandle.lhs,v 1.59 2000/07/07 11:03:58 simonmar Exp $
4 % (c) The AQUA Project, Glasgow University, 1994-2000
7 \section[PrelHandle]{Module @PrelHandle@}
9 This module defines Haskell {\em handles} and the basic operations
10 which are supported for them.
13 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
14 #include "cbits/stgerror.h"
16 #ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
17 module PrelHandle where
21 import PrelAddr ( Addr, nullAddr )
22 import PrelByteArr ( ByteArray(..) )
23 import PrelRead ( Read )
24 import PrelList ( span )
26 import PrelMaybe ( Maybe(..) )
29 import PrelNum ( toBig, Integer(..), Num(..) )
31 import PrelAddr ( Addr, nullAddr )
32 import PrelReal ( toInteger )
33 import PrelPack ( packString )
34 #ifndef __PARALLEL_HASKELL__
35 import PrelWeak ( addForeignFinalizer )
40 #ifndef __PARALLEL_HASKELL__
41 import PrelForeign ( makeForeignObj, mkForeignObj )
44 #endif /* ndef(__HUGS__) */
47 #define __CONCURRENT_HASKELL__
51 #ifndef __PARALLEL_HASKELL__
52 #define FILE_OBJECT ForeignObj
54 #define FILE_OBJECT Addr
59 mkBuffer__ :: FILE_OBJECT -> Int -> IO ()
60 mkBuffer__ fo sz_in_bytes = do
63 0 -> return nullAddr -- this has the effect of overwriting the pointer to the old buffer.
65 chunk <- allocMemory__ sz_in_bytes
67 then ioException (IOError Nothing ResourceExhausted "mkBuffer__" "not enough virtual memory")
69 setBuf fo chunk sz_in_bytes
72 %*********************************************************
74 \subsection{Types @Handle@, @Handle__@}
76 %*********************************************************
78 The @Handle@ and @Handle__@ types are defined in @IOBase@.
81 {-# INLINE newHandle #-}
82 newHandle :: Handle__ -> IO Handle
84 -- Use MVars for concurrent Haskell
85 newHandle hc = newMVar hc >>= \ h ->
89 %*********************************************************
91 \subsection{@withHandle@ operations}
93 %*********************************************************
95 In the concurrent world, handles are locked during use. This is done
96 by wrapping an MVar around the handle which acts as a mutex over
97 operations on the handle.
99 To avoid races, we use the following bracketing operations. The idea
100 is to obtain the lock, do some operation and replace the lock again,
101 whether the operation succeeded or failed. We also want to handle the
102 case where the thread receives an exception while processing the IO
103 operation: in these cases we also want to relinquish the lock.
105 There are three versions of @withHandle@: corresponding to the three
106 possible combinations of:
108 - the operation may side-effect the handle
109 - the operation may return a result
111 If the operation generates an error or an exception is raised, the
112 orignal handle is always replaced [ this is the case at the moment,
113 but we might want to revisit this in the future --SDM ].
116 withHandle :: Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
117 {-# INLINE withHandle #-}
118 withHandle (Handle h) act =
119 blockAsyncExceptions $ do
121 (h',v) <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
125 withHandle_ :: Handle -> (Handle__ -> IO a) -> IO a
126 {-# INLINE withHandle_ #-}
127 withHandle_ (Handle h) act =
128 blockAsyncExceptions $ do
130 v <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
134 withHandle__ :: Handle -> (Handle__ -> IO Handle__) -> IO ()
135 {-# INLINE withHandle__ #-}
136 withHandle__ (Handle h) act =
137 blockAsyncExceptions $ do
139 h' <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
144 nullFile__ is only used for closed handles, plugging it in as a null
145 file object reference.
148 nullFile__ :: FILE_OBJECT
150 #ifndef __PARALLEL_HASKELL__
151 unsafePerformIO (makeForeignObj nullAddr (return ()))
157 mkClosedHandle__ :: Handle__
159 Handle__ { haFO__ = nullFile__,
160 haType__ = ClosedHandle,
161 haBufferMode__ = NoBuffering,
162 haFilePath__ = "closed file",
166 mkErrorHandle__ :: IOException -> Handle__
167 mkErrorHandle__ ioe =
168 Handle__ { haFO__ = nullFile__,
169 haType__ = (ErrorHandle ioe),
170 haBufferMode__ = NoBuffering,
171 haFilePath__ = "error handle",
176 %*********************************************************
178 \subsection{Handle Finalizers}
180 %*********************************************************
183 stdHandleFinalizer :: Handle -> IO ()
184 stdHandleFinalizer (Handle hdl) = do
185 handle <- takeMVar hdl
186 let fo = haFO__ handle
188 freeBuffers (haBuffers__ handle)
190 handleFinalizer :: Handle -> IO ()
191 handleFinalizer (Handle hdl) = do
192 handle <- takeMVar hdl
193 let fo = haFO__ handle
195 freeBuffers (haBuffers__ handle)
197 freeBuffers [] = return ()
198 freeBuffers (b:bs) = do { free b; freeBuffers bs }
200 foreign import "libHS_cbits" "freeStdFileObject" unsafe
201 freeStdFileObject :: FILE_OBJECT -> IO ()
202 foreign import "libHS_cbits" "freeFileObject" unsafe
203 freeFileObject :: FILE_OBJECT -> IO ()
204 foreign import "free" unsafe
205 free :: Addr -> IO ()
208 %*********************************************************
210 \subsection[StdHandles]{Standard handles}
212 %*********************************************************
214 Three handles are allocated during program initialisation. The first
215 two manage input or output from the Haskell program's standard input
216 or output channel respectively. The third manages output to the
217 standard error channel. These handles are initially open.
221 stdin, stdout, stderr :: Handle
223 stdout = unsafePerformIO (do
224 rc <- getLock (1::Int) (1::Int) -- ConcHask: SAFE, won't block
226 0 -> newHandle (mkClosedHandle__)
228 fo <- openStdFile (1::Int)
229 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
231 #ifndef __PARALLEL_HASKELL__
232 fo <- mkForeignObj fo
233 -- I know this is deprecated, but I couldn't bring myself
234 -- to move fixIO into the prelude just so I could use makeForeignObj.
239 /* I dont care what the Haskell report says, in an interactive system,
240 * stdout should be unbuffered by default.
244 (bm, bf_size) <- getBMode__ fo
245 mkBuffer__ fo bf_size
247 hdl <- newHandle (Handle__ fo WriteHandle bm "stdout" [])
249 #ifndef __PARALLEL_HASKELL__
250 addForeignFinalizer fo (stdHandleFinalizer hdl)
254 _ -> do ioError <- constructError "stdout"
255 newHandle (mkErrorHandle__ ioError)
258 stdin = unsafePerformIO (do
259 rc <- getLock (0::Int) (0::Int) -- ConcHask: SAFE, won't block
261 0 -> newHandle (mkClosedHandle__)
263 fo <- openStdFile (0::Int)
264 (1::Int){-readable-} -- ConcHask: SAFE, won't block
266 #ifndef __PARALLEL_HASKELL__
267 fo <- mkForeignObj fo
269 (bm, bf_size) <- getBMode__ fo
270 mkBuffer__ fo bf_size
271 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin" [])
272 -- when stdin and stdout are both connected to a terminal, ensure
273 -- that anything buffered on stdout is flushed prior to reading from
275 #ifndef __PARALLEL_HASKELL__
276 addForeignFinalizer fo (stdHandleFinalizer hdl)
278 hConnectTerms stdout hdl
280 _ -> do ioError <- constructError "stdin"
281 newHandle (mkErrorHandle__ ioError)
285 stderr = unsafePerformIO (do
286 rc <- getLock (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
288 0 -> newHandle (mkClosedHandle__)
290 fo <- openStdFile (2::Int)
291 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
293 #ifndef __PARALLEL_HASKELL__
294 fo <- mkForeignObj fo
296 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr" [])
297 -- when stderr and stdout are both connected to a terminal, ensure
298 -- that anything buffered on stdout is flushed prior to writing to
300 #ifndef __PARALLEL_HASKELL__
301 addForeignFinalizer fo (stdHandleFinalizer hdl)
303 hConnectTo stdout hdl
306 _ -> do ioError <- constructError "stderr"
307 newHandle (mkErrorHandle__ ioError)
311 %*********************************************************
313 \subsection[OpeningClosing]{Opening and Closing Files}
315 %*********************************************************
318 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
319 deriving (Eq, Ord, Ix, Enum, Read, Show)
324 deriving (Eq, Read, Show)
326 openFile :: FilePath -> IOMode -> IO Handle
327 openFile fp im = openFileEx fp (TextMode im)
329 openFileEx :: FilePath -> IOModeEx -> IO Handle
332 fo <- primOpenFile (packString f)
334 (binary::Int) -- ConcHask: SAFE, won't block
335 if fo /= nullAddr then do
336 #ifndef __PARALLEL_HASKELL__
337 fo <- mkForeignObj fo
339 (bm, bf_size) <- getBMode__ fo
340 mkBuffer__ fo bf_size
341 hdl <- newHandle (Handle__ fo htype bm f [])
342 #ifndef __PARALLEL_HASKELL__
343 addForeignFinalizer fo (handleFinalizer hdl)
347 constructErrorAndFailWithInfo "openFile" f
351 BinaryMode bmo -> (bmo, 1)
352 TextMode tmo -> (tmo, 0)
362 ReadMode -> ReadHandle
363 WriteMode -> WriteHandle
364 AppendMode -> AppendHandle
365 ReadWriteMode -> ReadWriteHandle
368 Computation $openFile file mode$ allocates and returns a new, open
369 handle to manage the file {\em file}. It manages input if {\em mode}
370 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
371 and both input and output if mode is $ReadWriteMode$.
373 If the file does not exist and it is opened for output, it should be
374 created as a new file. If {\em mode} is $WriteMode$ and the file
375 already exists, then it should be truncated to zero length. The
376 handle is positioned at the end of the file if {\em mode} is
377 $AppendMode$, and otherwise at the beginning (in which case its
378 internal position is 0).
380 Implementations should enforce, locally to the Haskell process,
381 multiple-reader single-writer locking on files, which is to say that
382 there may either be many handles on the same file which manage input,
383 or just one handle on the file which manages output. If any open or
384 semi-closed handle is managing a file for output, no new handle can be
385 allocated for that file. If any open or semi-closed handle is
386 managing a file for input, new handles can only be allocated if they
387 do not manage output.
389 Two files are the same if they have the same absolute name. An
390 implementation is free to impose stricter conditions.
393 hClose :: Handle -> IO ()
396 withHandle__ handle $ \ handle_ -> do
397 case haType__ handle_ of
398 ErrorHandle theError -> ioException theError
399 ClosedHandle -> return handle_
401 rc <- closeFile (haFO__ handle_)
402 (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
403 {- We explicitly close a file object so that we can be told
404 if there were any errors. Note that after @hClose@
405 has been performed, the ForeignObj embedded in the Handle
406 is still lying around in the heap, so care is taken
407 to avoid closing the file object when the ForeignObj
408 is finalized. (we overwrite the file ptr in the underlying
409 FileObject with a NULL as part of closeFile())
413 then constructErrorAndFail "hClose"
415 -- free the spare buffers (except the handle buffer)
416 -- associated with this handle.
417 else do freeBuffers (haBuffers__ handle_)
418 return (handle_{ haType__ = ClosedHandle,
423 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
424 computation finishes, any items buffered for output and not already
425 sent to the operating system are flushed as for $flush$.
427 %*********************************************************
429 \subsection[FileSize]{Detecting the size of a file}
431 %*********************************************************
434 For a handle {\em hdl} which attached to a physical file, $hFileSize
435 hdl$ returns the size of {\em hdl} in terms of the number of items
436 which can be read from {\em hdl}.
439 hFileSize :: Handle -> IO Integer
441 withHandle_ handle $ \ handle_ -> do
442 case haType__ handle_ of
443 ErrorHandle theError -> ioException theError
444 ClosedHandle -> ioe_closedHandle "hFileSize" handle
445 SemiClosedHandle -> ioe_closedHandle "hFileSize" handle
448 mem <- primNewByteArray 8{-sizeof_int64-}
449 rc <- fileSize_int64 (haFO__ handle_) mem -- ConcHask: SAFE, won't block
451 result <- primReadInt64Array mem 0
452 return (primInt64ToInteger result)
454 constructErrorAndFail "hFileSize"
457 -- HACK! We build a unique MP_INT of the right shape to hold
458 -- a single unsigned word, and we let the C routine
459 -- change the data bits
461 case int2Integer# 1# of
463 rc <- fileSize (haFO__ handle_) d -- ConcHask: SAFE, won't block
464 if rc == (0::Int) then
467 constructErrorAndFail "hFileSize"
471 %*********************************************************
473 \subsection[EOF]{Detecting the End of Input}
475 %*********************************************************
478 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
479 @True@ if no further input can be taken from @hdl@ or for a
480 physical file, if the current I/O position is equal to the length of
481 the file. Otherwise, it returns @False@.
484 hIsEOF :: Handle -> IO Bool
486 rc <- mayBlockRead "hIsEOF" handle fileEOF
490 _ -> constructErrorAndFail "hIsEOF"
496 %*********************************************************
498 \subsection[Buffering]{Buffering Operations}
500 %*********************************************************
502 Three kinds of buffering are supported: line-buffering,
503 block-buffering or no-buffering. See @IOBase@ for definition
504 and further explanation of what the type represent.
506 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
507 handle {\em hdl} on subsequent reads and writes.
511 If {\em mode} is @LineBuffering@, line-buffering should be
514 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
515 should be enabled if possible. The size of the buffer is {\em n} items
516 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
518 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
521 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
522 to @NoBuffering@, then any items in the output buffer are written to
523 the device, and any items in the input buffer are discarded. The
524 default buffering mode when a handle is opened is
525 implementation-dependent and may depend on the object which is
526 attached to that handle.
529 hSetBuffering :: Handle -> BufferMode -> IO ()
531 hSetBuffering handle mode =
533 BlockBuffering (Just n)
534 | n <= 0 -> ioException
535 (IOError (Just handle)
538 ("illegal buffer size " ++ showsPrec 9 n []))
539 -- 9 => should be parens'ified.
541 withHandle__ handle $ \ handle_ -> do
542 case haType__ handle_ of
543 ErrorHandle theError -> ioException theError
544 ClosedHandle -> ioe_closedHandle "hSetBuffering" handle
547 - we flush the old buffer regardless of whether
548 the new buffer could fit the contents of the old buffer
550 - allow a handle's buffering to change even if IO has
551 occurred (ANSI C spec. does not allow this, nor did
552 the previous implementation of IO.hSetBuffering).
553 - a non-standard extension is to allow the buffering
554 of semi-closed handles to change [sof 6/98]
556 let fo = haFO__ handle_
557 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
560 return (handle_{ haBufferMode__ = mode })
562 -- Note: failure to change the buffer size will cause old buffer to be flushed.
563 constructErrorAndFail "hSetBuffering"
569 BlockBuffering Nothing -> -2
570 BlockBuffering (Just n) -> n
573 The action @hFlush hdl@ causes any items buffered for output
574 in handle {\em hdl} to be sent immediately to the operating
578 hFlush :: Handle -> IO ()
580 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
581 let fo = haFO__ handle_
582 rc <- mayBlock fo (flushFile fo) -- ConcHask: UNSAFE, may block
586 constructErrorAndFail "hFlush"
591 %*********************************************************
593 \subsection[Seeking]{Repositioning Handles}
595 %*********************************************************
600 Handle -- Q: should this be a weak or strong ref. to the handle?
601 -- [what's the winning argument for it not being strong? --sof]
604 instance Eq HandlePosn where
605 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
607 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
608 -- We represent it as an Integer on the Haskell side, but
609 -- cheat slightly in that hGetPosn calls upon a C helper
610 -- that reports the position back via (merely) an Int.
611 type HandlePosition = Integer
613 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
614 mkHandlePosn h p = HandlePosn h p
616 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
617 deriving (Eq, Ord, Ix, Enum, Read, Show)
620 Computation @hGetPosn hdl@ returns the current I/O
621 position of {\em hdl} as an abstract position. Computation
622 $hSetPosn p$ sets the position of {\em hdl}
623 to a previously obtained position {\em p}.
626 hGetPosn :: Handle -> IO HandlePosn
628 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
629 posn <- getFilePosn (haFO__ handle_) -- ConcHask: SAFE, won't block
630 if posn /= -1 then do
631 return (mkHandlePosn handle (fromInt posn))
633 constructErrorAndFail "hGetPosn"
635 hSetPosn :: HandlePosn -> IO ()
636 hSetPosn (HandlePosn handle i@(S# _)) = hSetPosn (HandlePosn handle (toBig i))
637 hSetPosn (HandlePosn handle (J# s# d#)) =
638 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do
639 -- not as silly as it looks: the handle may have been closed in the meantime.
640 let fo = haFO__ handle_
641 rc <- mayBlock fo (setFilePosn fo (I# s#) d#) -- ConcHask: UNSAFE, may block
645 constructErrorAndFail "hSetPosn"
648 The action @hSeek hdl mode i@ sets the position of handle
649 @hdl@ depending on @mode@. If @mode@ is
651 * AbsoluteSeek - The position of @hdl@ is set to @i@.
652 * RelativeSeek - The position of @hdl@ is set to offset @i@ from
653 the current position.
654 * SeekFromEnd - The position of @hdl@ is set to offset @i@ from
657 Some handles may not be seekable (see @hIsSeekable@), or only
658 support a subset of the possible positioning operations (e.g. it may
659 only be possible to seek to the end of a tape, or to a positive
660 offset from the beginning or current position).
662 It is not possible to set a negative I/O position, or for a physical
663 file, an I/O position beyond the current end-of-file.
666 - when seeking using @SeekFromEnd@, positive offsets (>=0) means
667 seeking at or past EOF.
668 - relative seeking on buffered handles can lead to non-obvious results.
671 hSeek :: Handle -> SeekMode -> Integer -> IO ()
673 hSeek handle mode offset =
674 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
675 let fo = haFO__ handle_
676 rc <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
678 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
679 hSeek handle mode (J# s# d#) =
680 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
681 let fo = haFO__ handle_
682 rc <- mayBlock fo (seekFile fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
687 constructErrorAndFail "hSeek"
690 whence = case mode of
696 %*********************************************************
698 \subsection[Query]{Handle Properties}
700 %*********************************************************
702 A number of operations return information about the properties of a
703 handle. Each of these operations returns $True$ if the
704 handle has the specified property, and $False$
707 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
708 {\em hdl} is not block-buffered. Otherwise it returns
709 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
710 $( Just n )$ for block-buffering of {\em n} bytes.
713 hIsOpen :: Handle -> IO Bool
715 withHandle_ handle $ \ handle_ -> do
716 case haType__ handle_ of
717 ErrorHandle theError -> ioException theError
718 ClosedHandle -> return False
719 SemiClosedHandle -> return False
722 hIsClosed :: Handle -> IO Bool
724 withHandle_ handle $ \ handle_ -> do
725 case haType__ handle_ of
726 ErrorHandle theError -> ioException theError
727 ClosedHandle -> return True
730 {- not defined, nor exported, but mentioned
731 here for documentation purposes:
733 hSemiClosed :: Handle -> IO Bool
737 return (not (ho || hc))
740 hIsReadable :: Handle -> IO Bool
742 withHandle_ handle $ \ handle_ -> do
743 case haType__ handle_ of
744 ErrorHandle theError -> ioException theError
745 ClosedHandle -> ioe_closedHandle "hIsReadable" handle
746 SemiClosedHandle -> ioe_closedHandle "hIsReadable" handle
747 htype -> return (isReadable htype)
749 isReadable ReadHandle = True
750 isReadable ReadWriteHandle = True
753 hIsWritable :: Handle -> IO Bool
755 withHandle_ handle $ \ handle_ -> do
756 case haType__ handle_ of
757 ErrorHandle theError -> ioException theError
758 ClosedHandle -> ioe_closedHandle "hIsWritable" handle
759 SemiClosedHandle -> ioe_closedHandle "hIsWritable" handle
760 htype -> return (isWritable htype)
762 isWritable AppendHandle = True
763 isWritable WriteHandle = True
764 isWritable ReadWriteHandle = True
768 getBMode__ :: FILE_OBJECT -> IO (BufferMode, Int)
770 rc <- getBufferMode fo -- ConcHask: SAFE, won't block
772 0 -> return (NoBuffering, 0)
773 -1 -> return (LineBuffering, default_buffer_size)
774 -2 -> return (BlockBuffering Nothing, default_buffer_size)
775 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
776 n -> return (BlockBuffering (Just n), n)
778 default_buffer_size :: Int
779 default_buffer_size = const_BUFSIZ
782 Querying how a handle buffers its data:
785 hGetBuffering :: Handle -> IO BufferMode
786 hGetBuffering handle =
787 withHandle_ handle $ \ handle_ -> do
788 case haType__ handle_ of
789 ErrorHandle theError -> ioException theError
790 ClosedHandle -> ioe_closedHandle "hGetBuffering" handle
793 We're being non-standard here, and allow the buffering
794 of a semi-closed handle to be queried. -- sof 6/98
796 return (haBufferMode__ handle_) -- could be stricter..
800 hIsSeekable :: Handle -> IO Bool
802 withHandle_ handle $ \ handle_ -> do
803 case haType__ handle_ of
804 ErrorHandle theError -> ioException theError
805 ClosedHandle -> ioe_closedHandle "hIsSeekable" handle
806 SemiClosedHandle -> ioe_closedHandle "hIsSeekable" handle
807 AppendHandle -> return False
809 rc <- seekFileP (haFO__ handle_) -- ConcHask: SAFE, won't block
813 _ -> constructErrorAndFail "hIsSeekable"
817 %*********************************************************
819 \subsection{Changing echo status}
821 %*********************************************************
823 Non-standard GHC extension is to allow the echoing status
824 of a handles connected to terminals to be reconfigured:
827 hSetEcho :: Handle -> Bool -> IO ()
828 hSetEcho handle on = do
829 isT <- hIsTerminalDevice handle
833 withHandle_ handle $ \ handle_ -> do
834 case haType__ handle_ of
835 ErrorHandle theError -> ioException theError
836 ClosedHandle -> ioe_closedHandle "hSetEcho" handle
838 rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0) -- ConcHask: SAFE, won't block
841 else constructErrorAndFail "hSetEcho"
843 hGetEcho :: Handle -> IO Bool
845 isT <- hIsTerminalDevice handle
849 withHandle_ handle $ \ handle_ -> do
850 case haType__ handle_ of
851 ErrorHandle theError -> ioException theError
852 ClosedHandle -> ioe_closedHandle "hGetEcho" handle
854 rc <- getTerminalEcho (haFO__ handle_) -- ConcHask: SAFE, won't block
858 _ -> constructErrorAndFail "hSetEcho"
860 hIsTerminalDevice :: Handle -> IO Bool
861 hIsTerminalDevice handle = do
862 withHandle_ handle $ \ handle_ -> do
863 case haType__ handle_ of
864 ErrorHandle theError -> ioException theError
865 ClosedHandle -> ioe_closedHandle "hIsTerminalDevice" handle
867 rc <- isTerminalDevice (haFO__ handle_) -- ConcHask: SAFE, won't block
871 _ -> constructErrorAndFail "hIsTerminalDevice"
875 hConnectTerms :: Handle -> Handle -> IO ()
876 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
878 hConnectTo :: Handle -> Handle -> IO ()
879 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
881 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
882 hConnectHdl_ hW hR is_tty =
883 wantRWHandle "hConnectTo" hW $ \ hW_ ->
884 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
885 setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
888 As an extension, we also allow characters to be pushed back.
889 Like ANSI C stdio, we guarantee no more than one character of
890 pushback. (For unbuffered channels, the (default) push-back limit is
894 hUngetChar :: Handle -> Char -> IO ()
895 hUngetChar handle c =
896 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
897 rc <- ungetChar (haFO__ handle_) c -- ConcHask: SAFE, won't block
899 then constructErrorAndFail "hUngetChar"
905 Hoisting files in in one go is sometimes useful, so we support
906 this as an extension:
909 -- in one go, read file into an externally allocated buffer.
910 slurpFile :: FilePath -> IO (Addr, Int)
912 handle <- openFile fname ReadMode
913 sz <- hFileSize handle
914 if sz > toInteger (maxBound::Int) then
915 ioError (userError "slurpFile: file too big")
917 let sz_i = fromInteger sz
918 chunk <- allocMemory__ sz_i
922 constructErrorAndFail "slurpFile"
924 rc <- withHandle_ handle ( \ handle_ -> do
925 let fo = haFO__ handle_
926 mayBlock fo (readChunk fo chunk 0 sz_i) -- ConcHask: UNSAFE, may block.
930 then constructErrorAndFail "slurpFile"
931 else return (chunk, rc)
935 Sometimes it's useful to get at the file descriptor that
936 the Handle contains..
939 getHandleFd :: Handle -> IO Int
941 withHandle_ handle $ \ handle_ -> do
942 case (haType__ handle_) of
943 ErrorHandle theError -> ioException theError
944 ClosedHandle -> ioe_closedHandle "getHandleFd" handle
946 fd <- getFileFd (haFO__ handle_)
951 %*********************************************************
953 \subsection{Miscellaneous}
955 %*********************************************************
957 These three functions are meant to get things out of @IOErrors@.
962 ioeGetFileName :: IOError -> Maybe FilePath
963 ioeGetErrorString :: IOError -> String
964 ioeGetHandle :: IOError -> Maybe Handle
966 ioeGetHandle (IOException (IOError h _ _ _)) = h
967 ioeGetHandle _ = error "IO.ioeGetHandle: not an IO error"
969 ioeGetErrorString (IOException (IOError _ iot _ str)) =
973 ioeGetErrorString _ = error "IO.ioeGetErrorString: not an IO error"
975 ioeGetFileName (IOException (IOError _ _ _ str)) =
976 case span (/=':') str of
979 ioeGetFileName _ = error "IO.ioeGetFileName: not an IO error"
982 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
983 PrelMain.mainIO) and report them - topHandler is the exception
984 handler they should use for this:
987 -- make sure we handle errors while reporting the error!
988 -- (e.g. evaluating the string passed to 'error' might generate
989 -- another error, etc.)
990 topHandler :: Bool -> Exception -> IO ()
991 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
993 real_handler :: Bool -> Exception -> IO ()
994 real_handler bombOut ex =
996 AsyncException StackOverflow -> reportStackOverflow bombOut
997 ErrorCall s -> reportError bombOut s
998 other -> reportError bombOut (showsPrec 0 other "\n")
1000 reportStackOverflow :: Bool -> IO ()
1001 reportStackOverflow bombOut = do
1002 (hFlush stdout) `catchException` (\ _ -> return ())
1003 callStackOverflowHook
1009 reportError :: Bool -> String -> IO ()
1010 reportError bombOut str = do
1011 (hFlush stdout) `catchException` (\ _ -> return ())
1012 let bs@(ByteArray _ len _) = packString str
1013 writeErrString addrOf_ErrorHdrHook bs len
1019 foreign import ccall "addrOf_ErrorHdrHook" unsafe
1020 addrOf_ErrorHdrHook :: Addr
1022 foreign import ccall "writeErrString__" unsafe
1023 writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1025 -- SUP: Are the hooks allowed to re-enter Haskell land? If yes, remove the unsafe below.
1026 foreign import ccall "stackOverflow" unsafe
1027 callStackOverflowHook :: IO ()
1029 foreign import ccall "stg_exit" unsafe
1030 stg_exit :: Int -> IO ()
1034 A number of operations want to get at a readable or writeable handle, and fail
1038 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1039 wantReadableHandle fun handle act =
1040 withHandle_ handle $ \ handle_ -> do
1041 case haType__ handle_ of
1042 ErrorHandle theError -> ioException theError
1043 ClosedHandle -> ioe_closedHandle fun handle
1044 SemiClosedHandle -> ioe_closedHandle fun handle
1045 AppendHandle -> ioException not_readable_error
1046 WriteHandle -> ioException not_readable_error
1049 not_readable_error =
1050 IOError (Just handle) IllegalOperation fun
1051 ("handle is not open for reading")
1053 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1054 wantWriteableHandle fun handle act =
1055 withHandle_ handle $ \ handle_ ->
1056 checkWriteableHandle fun handle handle_ (act handle_)
1058 wantWriteableHandle_ :: String -> Handle -> (Handle__ -> IO (Handle__, a)) -> IO a
1059 wantWriteableHandle_ fun handle act =
1060 withHandle handle $ \ handle_ ->
1061 checkWriteableHandle fun handle handle_ (act handle_)
1063 checkWriteableHandle fun handle handle_ act
1064 = case haType__ handle_ of
1065 ErrorHandle theError -> ioError (IOException theError)
1066 ClosedHandle -> ioe_closedHandle fun handle
1067 SemiClosedHandle -> ioe_closedHandle fun handle
1068 ReadHandle -> ioError not_writeable_error
1071 not_writeable_error =
1072 IOException (IOError (Just handle) IllegalOperation fun
1073 ("handle is not open for writing"))
1075 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1076 wantRWHandle fun handle act =
1077 withHandle_ handle $ \ handle_ -> do
1078 case haType__ handle_ of
1079 ErrorHandle theError -> ioException theError
1080 ClosedHandle -> ioe_closedHandle fun handle
1081 SemiClosedHandle -> ioe_closedHandle fun handle
1084 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1085 wantSeekableHandle fun handle act =
1086 withHandle_ handle $ \ handle_ -> do
1087 case haType__ handle_ of
1088 ErrorHandle theError -> ioException theError
1089 ClosedHandle -> ioe_closedHandle fun handle
1090 SemiClosedHandle -> ioe_closedHandle fun handle
1093 not_seekable_error =
1094 IOException (IOError (Just handle)
1095 IllegalOperation fun
1096 ("handle is not seekable"))
1100 Internal function for creating an @IOError@ representing the
1101 access to a closed file.
1104 ioe_closedHandle :: String -> Handle -> IO a
1105 ioe_closedHandle fun h = ioError (IOException (IOError (Just h) IllegalOperation fun
1106 "handle is closed"))
1109 Internal helper functions for Concurrent Haskell implementation
1113 mayBlock :: FILE_OBJECT -> IO Int -> IO Int
1114 mayBlock fo act = do
1117 -5 -> do -- (possibly blocking) read
1120 mayBlock fo act -- input available, re-try
1121 -6 -> do -- (possibly blocking) write
1124 mayBlock fo act -- output possible
1125 -7 -> do -- (possibly blocking) write on connected handle
1126 fd <- getConnFileFd fo
1128 mayBlock fo act -- output possible
1137 mayBlockRead :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1138 mayBlockRead fname handle fn = do
1139 r <- wantReadableHandle fname handle $ \ handle_ -> do
1140 let fo = haFO__ handle_
1143 -5 -> do -- (possibly blocking) read
1145 return (BlockRead fd)
1146 -6 -> do -- (possibly blocking) write
1148 return (BlockWrite fd)
1149 -7 -> do -- (possibly blocking) write on connected handle
1150 fd <- getConnFileFd fo
1151 return (BlockWrite fd)
1154 then return (NoBlock rc)
1155 else constructErrorAndFail fname
1159 mayBlockRead fname handle fn
1162 mayBlockRead fname handle fn
1163 NoBlock c -> return c
1165 mayBlockRead' :: String -> Handle
1166 -> (FILE_OBJECT -> IO Int)
1167 -> (FILE_OBJECT -> Int -> IO a)
1169 mayBlockRead' fname handle fn io = do
1170 r <- wantReadableHandle fname handle $ \ handle_ -> do
1171 let fo = haFO__ handle_
1174 -5 -> do -- (possibly blocking) read
1176 return (BlockRead fd)
1177 -6 -> do -- (possibly blocking) write
1179 return (BlockWrite fd)
1180 -7 -> do -- (possibly blocking) write on connected handle
1181 fd <- getConnFileFd fo
1182 return (BlockWrite fd)
1185 then do a <- io fo rc
1187 else constructErrorAndFail fname
1191 mayBlockRead' fname handle fn io
1194 mayBlockRead' fname handle fn io
1195 NoBlock c -> return c
1197 mayBlockWrite :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1198 mayBlockWrite fname handle fn = do
1199 r <- wantWriteableHandle fname handle $ \ handle_ -> do
1200 let fo = haFO__ handle_
1203 -5 -> do -- (possibly blocking) read
1205 return (BlockRead fd)
1206 -6 -> do -- (possibly blocking) write
1208 return (BlockWrite fd)
1209 -7 -> do -- (possibly blocking) write on connected handle
1210 fd <- getConnFileFd fo
1211 return (BlockWrite fd)
1214 then return (NoBlock rc)
1215 else constructErrorAndFail fname
1219 mayBlockWrite fname handle fn
1222 mayBlockWrite fname handle fn
1223 NoBlock c -> return c
1226 Foreign import declarations of helper functions:
1231 type Bytes = PrimByteArray RealWorld
1233 type Bytes = ByteArray#
1236 foreign import "libHS_cbits" "inputReady" unsafe
1237 inputReady :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1238 foreign import "libHS_cbits" "fileGetc" unsafe
1239 fileGetc :: FILE_OBJECT -> IO Int
1240 foreign import "libHS_cbits" "fileLookAhead" unsafe
1241 fileLookAhead :: FILE_OBJECT -> IO Int
1242 foreign import "libHS_cbits" "readBlock" unsafe
1243 readBlock :: FILE_OBJECT -> IO Int
1244 foreign import "libHS_cbits" "readLine" unsafe
1245 readLine :: FILE_OBJECT -> IO Int
1246 foreign import "libHS_cbits" "readChar" unsafe
1247 readChar :: FILE_OBJECT -> IO Int
1248 foreign import "libHS_cbits" "writeFileObject" unsafe
1249 writeFileObject :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1250 foreign import "libHS_cbits" "filePutc" unsafe
1251 filePutc :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1252 foreign import "libHS_cbits" "write_" unsafe
1253 write_ :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1254 foreign import "libHS_cbits" "getBufStart" unsafe
1255 getBufStart :: FILE_OBJECT -> Int -> IO Addr
1256 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1257 getWriteableBuf :: FILE_OBJECT -> IO Addr
1258 foreign import "libHS_cbits" "getBuf" unsafe
1259 getBuf :: FILE_OBJECT -> IO Addr
1260 foreign import "libHS_cbits" "getBufWPtr" unsafe
1261 getBufWPtr :: FILE_OBJECT -> IO Int
1262 foreign import "libHS_cbits" "setBufWPtr" unsafe
1263 setBufWPtr :: FILE_OBJECT -> Int -> IO ()
1264 foreign import "libHS_cbits" "closeFile" unsafe
1265 closeFile :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1266 foreign import "libHS_cbits" "fileEOF" unsafe
1267 fileEOF :: FILE_OBJECT -> IO Int{-ret code-}
1268 foreign import "libHS_cbits" "setBuffering" unsafe
1269 setBuffering :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1270 foreign import "libHS_cbits" "flushFile" unsafe
1271 flushFile :: FILE_OBJECT -> IO Int{-ret code-}
1272 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1273 flushConnectedBuf :: FILE_OBJECT -> IO ()
1274 foreign import "libHS_cbits" "getBufferMode" unsafe
1275 getBufferMode :: FILE_OBJECT -> IO Int{-ret code-}
1277 foreign import "libHS_cbits" "seekFile_int64" unsafe
1278 seekFile :: FILE_OBJECT -> Int -> Int64 -> IO Int
1280 foreign import "libHS_cbits" "seekFile" unsafe
1281 seekFile :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1284 foreign import "libHS_cbits" "seekFileP" unsafe
1285 seekFileP :: FILE_OBJECT -> IO Int{-ret code-}
1286 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1287 setTerminalEcho :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1288 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1289 getTerminalEcho :: FILE_OBJECT -> IO Int{-ret code-}
1290 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1291 isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1292 foreign import "libHS_cbits" "setConnectedTo" unsafe
1293 setConnectedTo :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1294 foreign import "libHS_cbits" "ungetChar" unsafe
1295 ungetChar :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1296 foreign import "libHS_cbits" "readChunk" unsafe
1297 readChunk :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1298 foreign import "libHS_cbits" "getFileFd" unsafe
1299 getFileFd :: FILE_OBJECT -> IO Int{-fd-}
1301 foreign import "libHS_cbits" "fileSize_int64" unsafe
1302 fileSize_int64 :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1304 foreign import "libHS_cbits" "fileSize" unsafe
1305 fileSize :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1308 foreign import "libHS_cbits" "getFilePosn" unsafe
1309 getFilePosn :: FILE_OBJECT -> IO Int
1310 foreign import "libHS_cbits" "setFilePosn" unsafe
1311 setFilePosn :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1312 foreign import "libHS_cbits" "getConnFileFd" unsafe
1313 getConnFileFd :: FILE_OBJECT -> IO Int{-fd-}
1314 foreign import "libHS_cbits" "getLock" unsafe
1315 getLock :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1316 foreign import "libHS_cbits" "openStdFile" unsafe
1317 openStdFile :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1318 foreign import "libHS_cbits" "openFile" unsafe
1319 primOpenFile :: ByteArray Int{-CString-}
1322 -> IO Addr {-file obj-}
1323 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1326 foreign import "libHS_cbits" "setBinaryMode__" unsafe
1327 setBinaryMode :: FILE_OBJECT -> Int -> IO Int