1 % ------------------------------------------------------------------------------
2 % $Id: PrelHandle.lhs,v 1.65 2001/01/11 07:04:16 qrczak 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 ( break )
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 <- malloc sz_in_bytes
67 then ioException (IOError Nothing ResourceExhausted
68 "mkBuffer__" "not enough virtual memory" Nothing)
70 setBuf fo chunk sz_in_bytes
73 %*********************************************************
75 \subsection{Types @Handle@, @Handle__@}
77 %*********************************************************
79 The @Handle@ and @Handle__@ types are defined in @IOBase@.
82 {-# INLINE newHandle #-}
83 newHandle :: Handle__ -> IO Handle
85 -- Use MVars for concurrent Haskell
86 newHandle hc = newMVar hc >>= \ h ->
90 %*********************************************************
92 \subsection{@withHandle@ operations}
94 %*********************************************************
96 In the concurrent world, handles are locked during use. This is done
97 by wrapping an MVar around the handle which acts as a mutex over
98 operations on the handle.
100 To avoid races, we use the following bracketing operations. The idea
101 is to obtain the lock, do some operation and replace the lock again,
102 whether the operation succeeded or failed. We also want to handle the
103 case where the thread receives an exception while processing the IO
104 operation: in these cases we also want to relinquish the lock.
106 There are three versions of @withHandle@: corresponding to the three
107 possible combinations of:
109 - the operation may side-effect the handle
110 - the operation may return a result
112 If the operation generates an error or an exception is raised, the
113 orignal handle is always replaced [ this is the case at the moment,
114 but we might want to revisit this in the future --SDM ].
117 withHandle :: Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
118 {-# INLINE withHandle #-}
119 withHandle (Handle h) act =
122 (h',v) <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
126 withHandle_ :: Handle -> (Handle__ -> IO a) -> IO a
127 {-# INLINE withHandle_ #-}
128 withHandle_ (Handle h) act =
131 v <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
135 withHandle__ :: Handle -> (Handle__ -> IO Handle__) -> IO ()
136 {-# INLINE withHandle__ #-}
137 withHandle__ (Handle h) act =
140 h' <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
145 nullFile__ is only used for closed handles, plugging it in as a null
146 file object reference.
149 nullFile__ :: FILE_OBJECT
151 #ifndef __PARALLEL_HASKELL__
152 unsafePerformIO (makeForeignObj nullAddr (return ()))
158 mkClosedHandle__ :: Handle__
160 Handle__ { haFO__ = nullFile__,
161 haType__ = ClosedHandle,
162 haBufferMode__ = NoBuffering,
163 haFilePath__ = "closed file",
168 %*********************************************************
170 \subsection{Handle Finalizers}
172 %*********************************************************
175 stdHandleFinalizer :: Handle -> IO ()
176 stdHandleFinalizer (Handle hdl) = do
177 handle <- takeMVar hdl
178 let fo = haFO__ handle
180 freeBuffers (haBuffers__ handle)
182 handleFinalizer :: Handle -> IO ()
183 handleFinalizer (Handle hdl) = do
184 handle <- takeMVar hdl
185 let fo = haFO__ handle
187 freeBuffers (haBuffers__ handle)
189 freeBuffers [] = return ()
190 freeBuffers (b:bs) = do { free b; freeBuffers bs }
192 foreign import "libHS_cbits" "freeStdFileObject" unsafe
193 freeStdFileObject :: FILE_OBJECT -> IO ()
194 foreign import "libHS_cbits" "freeFileObject" unsafe
195 freeFileObject :: FILE_OBJECT -> IO ()
196 foreign import "free" unsafe
197 free :: Addr -> IO ()
200 %*********************************************************
202 \subsection[StdHandles]{Standard handles}
204 %*********************************************************
206 Three handles are allocated during program initialisation. The first
207 two manage input or output from the Haskell program's standard input
208 or output channel respectively. The third manages output to the
209 standard error channel. These handles are initially open.
213 stdin, stdout, stderr :: Handle
215 stdout = unsafePerformIO (do
216 rc <- getLock (1::Int) (1::Int) -- ConcHask: SAFE, won't block
218 0 -> newHandle (mkClosedHandle__)
220 fo <- openStdFile (1::Int)
221 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
223 #ifndef __PARALLEL_HASKELL__
224 fo <- mkForeignObj fo
225 -- I know this is deprecated, but I couldn't bring myself
226 -- to move fixIO into the prelude just so I could use makeForeignObj.
231 /* I dont care what the Haskell report says, in an interactive system,
232 * stdout should be unbuffered by default.
236 (bm, bf_size) <- getBMode__ fo
237 mkBuffer__ fo bf_size
239 hdl <- newHandle (Handle__ fo WriteHandle bm "stdout" [])
241 #ifndef __PARALLEL_HASKELL__
242 addForeignFinalizer fo (stdHandleFinalizer hdl)
246 _ -> constructErrorAndFail "stdout"
249 stdin = unsafePerformIO (do
250 rc <- getLock (0::Int) (0::Int) -- ConcHask: SAFE, won't block
252 0 -> newHandle (mkClosedHandle__)
254 fo <- openStdFile (0::Int)
255 (1::Int){-readable-} -- ConcHask: SAFE, won't block
257 #ifndef __PARALLEL_HASKELL__
258 fo <- mkForeignObj fo
260 (bm, bf_size) <- getBMode__ fo
261 mkBuffer__ fo bf_size
262 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin" [])
263 -- when stdin and stdout are both connected to a terminal, ensure
264 -- that anything buffered on stdout is flushed prior to reading from
266 #ifndef __PARALLEL_HASKELL__
267 addForeignFinalizer fo (stdHandleFinalizer hdl)
269 hConnectTerms stdout hdl
271 _ -> constructErrorAndFail "stdin"
275 stderr = unsafePerformIO (do
276 rc <- getLock (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
278 0 -> newHandle (mkClosedHandle__)
280 fo <- openStdFile (2::Int)
281 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
283 #ifndef __PARALLEL_HASKELL__
284 fo <- mkForeignObj fo
286 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr" [])
287 -- when stderr and stdout are both connected to a terminal, ensure
288 -- that anything buffered on stdout is flushed prior to writing to
290 #ifndef __PARALLEL_HASKELL__
291 addForeignFinalizer fo (stdHandleFinalizer hdl)
293 hConnectTo stdout hdl
296 _ -> constructErrorAndFail "stderr"
300 %*********************************************************
302 \subsection[OpeningClosing]{Opening and Closing Files}
304 %*********************************************************
307 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
308 deriving (Eq, Ord, Ix, Enum, Read, Show)
313 deriving (Eq, Read, Show)
315 openFile :: FilePath -> IOMode -> IO Handle
316 openFile fp im = openFileEx fp (TextMode im)
318 openFileEx :: FilePath -> IOModeEx -> IO Handle
321 fo <- primOpenFile (packString f)
323 (binary::Int) -- ConcHask: SAFE, won't block
324 if fo /= nullAddr then do
325 #ifndef __PARALLEL_HASKELL__
326 fo <- mkForeignObj fo
328 (bm, bf_size) <- getBMode__ fo
329 mkBuffer__ fo bf_size
330 hdl <- newHandle (Handle__ fo htype bm f [])
331 #ifndef __PARALLEL_HASKELL__
332 addForeignFinalizer fo (handleFinalizer hdl)
336 constructErrorAndFailWithInfo "openFile" f
340 BinaryMode bmo -> (bmo, 1)
341 TextMode tmo -> (tmo, 0)
351 ReadMode -> ReadHandle
352 WriteMode -> WriteHandle
353 AppendMode -> AppendHandle
354 ReadWriteMode -> ReadWriteHandle
357 Computation $openFile file mode$ allocates and returns a new, open
358 handle to manage the file {\em file}. It manages input if {\em mode}
359 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
360 and both input and output if mode is $ReadWriteMode$.
362 If the file does not exist and it is opened for output, it should be
363 created as a new file. If {\em mode} is $WriteMode$ and the file
364 already exists, then it should be truncated to zero length. The
365 handle is positioned at the end of the file if {\em mode} is
366 $AppendMode$, and otherwise at the beginning (in which case its
367 internal position is 0).
369 Implementations should enforce, locally to the Haskell process,
370 multiple-reader single-writer locking on files, which is to say that
371 there may either be many handles on the same file which manage input,
372 or just one handle on the file which manages output. If any open or
373 semi-closed handle is managing a file for output, no new handle can be
374 allocated for that file. If any open or semi-closed handle is
375 managing a file for input, new handles can only be allocated if they
376 do not manage output.
378 Two files are the same if they have the same absolute name. An
379 implementation is free to impose stricter conditions.
382 hClose :: Handle -> IO ()
385 withHandle__ handle $ \ handle_ -> do
386 case haType__ handle_ of
387 ClosedHandle -> return handle_
389 rc <- closeFile (haFO__ handle_)
390 (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
391 {- We explicitly close a file object so that we can be told
392 if there were any errors. Note that after @hClose@
393 has been performed, the ForeignObj embedded in the Handle
394 is still lying around in the heap, so care is taken
395 to avoid closing the file object when the ForeignObj
396 is finalized. (we overwrite the file ptr in the underlying
397 FileObject with a NULL as part of closeFile())
401 then constructErrorAndFail "hClose"
403 -- free the spare buffers (except the handle buffer)
404 -- associated with this handle.
405 else do freeBuffers (haBuffers__ handle_)
406 return (handle_{ haType__ = ClosedHandle,
410 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
411 computation finishes, any items buffered for output and not already
412 sent to the operating system are flushed as for $flush$.
414 %*********************************************************
416 \subsection[FileSize]{Detecting the size of a file}
418 %*********************************************************
421 For a handle {\em hdl} which attached to a physical file, $hFileSize
422 hdl$ returns the size of {\em hdl} in terms of the number of items
423 which can be read from {\em hdl}.
426 hFileSize :: Handle -> IO Integer
428 withHandle_ handle $ \ handle_ -> do
429 case haType__ handle_ of
430 ClosedHandle -> ioe_closedHandle "hFileSize" handle
431 SemiClosedHandle -> ioe_closedHandle "hFileSize" handle
434 mem <- primNewByteArray 8{-sizeof_int64-}
435 rc <- fileSize_int64 (haFO__ handle_) mem -- ConcHask: SAFE, won't block
437 result <- primReadInt64Array mem 0
438 return (primInt64ToInteger result)
440 constructErrorAndFail "hFileSize"
443 -- HACK! We build a unique MP_INT of the right shape to hold
444 -- a single unsigned word, and we let the C routine
445 -- change the data bits
447 case int2Integer# 1# of
449 rc <- fileSize (haFO__ handle_) d -- ConcHask: SAFE, won't block
450 if rc == (0::Int) then
453 constructErrorAndFail "hFileSize"
457 %*********************************************************
459 \subsection[EOF]{Detecting the End of Input}
461 %*********************************************************
464 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
465 @True@ if no further input can be taken from @hdl@ or for a
466 physical file, if the current I/O position is equal to the length of
467 the file. Otherwise, it returns @False@.
470 hIsEOF :: Handle -> IO Bool
472 rc <- mayBlockRead "hIsEOF" handle fileEOF
476 _ -> constructErrorAndFail "hIsEOF"
482 %*********************************************************
484 \subsection[Buffering]{Buffering Operations}
486 %*********************************************************
488 Three kinds of buffering are supported: line-buffering,
489 block-buffering or no-buffering. See @IOBase@ for definition
490 and further explanation of what the type represent.
492 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
493 handle {\em hdl} on subsequent reads and writes.
497 If {\em mode} is @LineBuffering@, line-buffering should be
500 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
501 should be enabled if possible. The size of the buffer is {\em n} items
502 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
504 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
507 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
508 to @NoBuffering@, then any items in the output buffer are written to
509 the device, and any items in the input buffer are discarded. The
510 default buffering mode when a handle is opened is
511 implementation-dependent and may depend on the object which is
512 attached to that handle.
515 hSetBuffering :: Handle -> BufferMode -> IO ()
517 hSetBuffering handle mode =
519 BlockBuffering (Just n)
520 | n <= 0 -> ioException
521 (IOError (Just handle)
524 ("illegal buffer size " ++ showsPrec 9 n [])
525 -- 9 => should be parens'ified.
528 withHandle__ handle $ \ handle_ -> do
529 case haType__ handle_ of
530 ClosedHandle -> ioe_closedHandle "hSetBuffering" handle
533 - we flush the old buffer regardless of whether
534 the new buffer could fit the contents of the old buffer
536 - allow a handle's buffering to change even if IO has
537 occurred (ANSI C spec. does not allow this, nor did
538 the previous implementation of IO.hSetBuffering).
539 - a non-standard extension is to allow the buffering
540 of semi-closed handles to change [sof 6/98]
542 let fo = haFO__ handle_
543 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
546 return (handle_{ haBufferMode__ = mode })
548 -- Note: failure to change the buffer size will cause old buffer to be flushed.
549 constructErrorAndFail "hSetBuffering"
555 BlockBuffering Nothing -> -2
556 BlockBuffering (Just n) -> n
559 The action @hFlush hdl@ causes any items buffered for output
560 in handle {\em hdl} to be sent immediately to the operating
564 hFlush :: Handle -> IO ()
566 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
567 let fo = haFO__ handle_
568 rc <- mayBlock fo (flushFile fo) -- ConcHask: UNSAFE, may block
572 constructErrorAndFail "hFlush"
577 %*********************************************************
579 \subsection[Seeking]{Repositioning Handles}
581 %*********************************************************
586 Handle -- Q: should this be a weak or strong ref. to the handle?
587 -- [what's the winning argument for it not being strong? --sof]
590 instance Eq HandlePosn where
591 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
593 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
594 -- We represent it as an Integer on the Haskell side, but
595 -- cheat slightly in that hGetPosn calls upon a C helper
596 -- that reports the position back via (merely) an Int.
597 type HandlePosition = Integer
599 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
600 mkHandlePosn h p = HandlePosn h p
602 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
603 deriving (Eq, Ord, Ix, Enum, Read, Show)
606 Computation @hGetPosn hdl@ returns the current I/O
607 position of {\em hdl} as an abstract position. Computation
608 $hSetPosn p$ sets the position of {\em hdl}
609 to a previously obtained position {\em p}.
612 hGetPosn :: Handle -> IO HandlePosn
614 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
615 posn <- getFilePosn (haFO__ handle_) -- ConcHask: SAFE, won't block
616 if posn /= -1 then do
617 return (mkHandlePosn handle (fromInt posn))
619 constructErrorAndFail "hGetPosn"
621 hSetPosn :: HandlePosn -> IO ()
622 hSetPosn (HandlePosn handle i@(S# _)) = hSetPosn (HandlePosn handle (toBig i))
623 hSetPosn (HandlePosn handle (J# s# d#)) =
624 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do
625 -- not as silly as it looks: the handle may have been closed in the meantime.
626 let fo = haFO__ handle_
627 rc <- mayBlock fo (setFilePosn fo (I# s#) d#) -- ConcHask: UNSAFE, may block
631 constructErrorAndFail "hSetPosn"
634 The action @hSeek hdl mode i@ sets the position of handle
635 @hdl@ depending on @mode@. If @mode@ is
637 * AbsoluteSeek - The position of @hdl@ is set to @i@.
638 * RelativeSeek - The position of @hdl@ is set to offset @i@ from
639 the current position.
640 * SeekFromEnd - The position of @hdl@ is set to offset @i@ from
643 Some handles may not be seekable (see @hIsSeekable@), or only
644 support a subset of the possible positioning operations (e.g. it may
645 only be possible to seek to the end of a tape, or to a positive
646 offset from the beginning or current position).
648 It is not possible to set a negative I/O position, or for a physical
649 file, an I/O position beyond the current end-of-file.
652 - when seeking using @SeekFromEnd@, positive offsets (>=0) means
653 seeking at or past EOF.
654 - relative seeking on buffered handles can lead to non-obvious results.
657 hSeek :: Handle -> SeekMode -> Integer -> IO ()
659 hSeek handle mode offset =
660 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
661 let fo = haFO__ handle_
662 rc <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
664 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
665 hSeek handle mode (J# s# d#) =
666 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
667 let fo = haFO__ handle_
668 rc <- mayBlock fo (seekFile fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
673 constructErrorAndFail "hSeek"
676 whence = case mode of
682 %*********************************************************
684 \subsection[Query]{Handle Properties}
686 %*********************************************************
688 A number of operations return information about the properties of a
689 handle. Each of these operations returns $True$ if the
690 handle has the specified property, and $False$
693 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
694 {\em hdl} is not block-buffered. Otherwise it returns
695 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
696 $( Just n )$ for block-buffering of {\em n} bytes.
699 hIsOpen :: Handle -> IO Bool
701 withHandle_ handle $ \ handle_ -> do
702 case haType__ handle_ of
703 ClosedHandle -> return False
704 SemiClosedHandle -> return False
707 hIsClosed :: Handle -> IO Bool
709 withHandle_ handle $ \ handle_ -> do
710 case haType__ handle_ of
711 ClosedHandle -> return True
714 {- not defined, nor exported, but mentioned
715 here for documentation purposes:
717 hSemiClosed :: Handle -> IO Bool
721 return (not (ho || hc))
724 hIsReadable :: Handle -> IO Bool
726 withHandle_ handle $ \ handle_ -> do
727 case haType__ handle_ of
728 ClosedHandle -> ioe_closedHandle "hIsReadable" handle
729 SemiClosedHandle -> ioe_closedHandle "hIsReadable" handle
730 htype -> return (isReadable htype)
732 isReadable ReadHandle = True
733 isReadable ReadWriteHandle = True
736 hIsWritable :: Handle -> IO Bool
738 withHandle_ handle $ \ handle_ -> do
739 case haType__ handle_ of
740 ClosedHandle -> ioe_closedHandle "hIsWritable" handle
741 SemiClosedHandle -> ioe_closedHandle "hIsWritable" handle
742 htype -> return (isWritable htype)
744 isWritable AppendHandle = True
745 isWritable WriteHandle = True
746 isWritable ReadWriteHandle = True
750 getBMode__ :: FILE_OBJECT -> IO (BufferMode, Int)
752 rc <- getBufferMode fo -- ConcHask: SAFE, won't block
754 0 -> return (NoBuffering, 0)
755 -1 -> return (LineBuffering, default_buffer_size)
756 -2 -> return (BlockBuffering Nothing, default_buffer_size)
757 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
758 n -> return (BlockBuffering (Just n), n)
760 default_buffer_size :: Int
761 default_buffer_size = const_BUFSIZ
764 Querying how a handle buffers its data:
767 hGetBuffering :: Handle -> IO BufferMode
768 hGetBuffering handle =
769 withHandle_ handle $ \ handle_ -> do
770 case haType__ handle_ of
771 ClosedHandle -> ioe_closedHandle "hGetBuffering" handle
774 We're being non-standard here, and allow the buffering
775 of a semi-closed handle to be queried. -- sof 6/98
777 return (haBufferMode__ handle_) -- could be stricter..
781 hIsSeekable :: Handle -> IO Bool
783 withHandle_ handle $ \ handle_ -> do
784 case haType__ handle_ of
785 ClosedHandle -> ioe_closedHandle "hIsSeekable" handle
786 SemiClosedHandle -> ioe_closedHandle "hIsSeekable" handle
787 AppendHandle -> return False
789 rc <- seekFileP (haFO__ handle_) -- ConcHask: SAFE, won't block
793 _ -> constructErrorAndFail "hIsSeekable"
797 %*********************************************************
799 \subsection{Changing echo status}
801 %*********************************************************
803 Non-standard GHC extension is to allow the echoing status
804 of a handles connected to terminals to be reconfigured:
807 hSetEcho :: Handle -> Bool -> IO ()
808 hSetEcho handle on = do
809 isT <- hIsTerminalDevice handle
813 withHandle_ handle $ \ handle_ -> do
814 case haType__ handle_ of
815 ClosedHandle -> ioe_closedHandle "hSetEcho" handle
817 rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0) -- ConcHask: SAFE, won't block
820 else constructErrorAndFail "hSetEcho"
822 hGetEcho :: Handle -> IO Bool
824 isT <- hIsTerminalDevice handle
828 withHandle_ handle $ \ handle_ -> do
829 case haType__ handle_ of
830 ClosedHandle -> ioe_closedHandle "hGetEcho" handle
832 rc <- getTerminalEcho (haFO__ handle_) -- ConcHask: SAFE, won't block
836 _ -> constructErrorAndFail "hSetEcho"
838 hIsTerminalDevice :: Handle -> IO Bool
839 hIsTerminalDevice handle = do
840 withHandle_ handle $ \ handle_ -> do
841 case haType__ handle_ of
842 ClosedHandle -> ioe_closedHandle "hIsTerminalDevice" handle
844 rc <- isTerminalDevice (haFO__ handle_) -- ConcHask: SAFE, won't block
848 _ -> constructErrorAndFail "hIsTerminalDevice"
852 hConnectTerms :: Handle -> Handle -> IO ()
853 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
855 hConnectTo :: Handle -> Handle -> IO ()
856 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
858 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
859 hConnectHdl_ hW hR is_tty =
860 wantRWHandle "hConnectTo" hW $ \ hW_ ->
861 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
862 setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
865 As an extension, we also allow characters to be pushed back.
866 Like ANSI C stdio, we guarantee no more than one character of
867 pushback. (For unbuffered channels, the (default) push-back limit is
871 hUngetChar :: Handle -> Char -> IO ()
872 hUngetChar handle c =
873 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
874 rc <- ungetChar (haFO__ handle_) c -- ConcHask: SAFE, won't block
876 then constructErrorAndFail "hUngetChar"
882 Hoisting files in in one go is sometimes useful, so we support
883 this as an extension:
886 -- in one go, read file into an externally allocated buffer.
887 slurpFile :: FilePath -> IO (Addr, Int)
889 handle <- openFile fname ReadMode
890 sz <- hFileSize handle
891 if sz > toInteger (maxBound::Int) then
892 ioError (userError "slurpFile: file too big")
894 let sz_i = fromInteger sz
899 constructErrorAndFail "slurpFile"
901 rc <- withHandle_ handle ( \ handle_ -> do
902 let fo = haFO__ handle_
903 mayBlock fo (readChunk fo chunk 0 sz_i) -- ConcHask: UNSAFE, may block.
907 then constructErrorAndFail "slurpFile"
908 else return (chunk, rc)
912 Sometimes it's useful to get at the file descriptor that
913 the Handle contains..
916 getHandleFd :: Handle -> IO Int
918 withHandle_ handle $ \ handle_ -> do
919 case (haType__ handle_) of
920 ClosedHandle -> ioe_closedHandle "getHandleFd" handle
922 fd <- getFileFd (haFO__ handle_)
927 %*********************************************************
929 \subsection{Miscellaneous}
931 %*********************************************************
933 These three functions are meant to get things out of @IOErrors@.
938 ioeGetFileName :: IOError -> Maybe FilePath
939 ioeGetErrorString :: IOError -> String
940 ioeGetHandle :: IOError -> Maybe Handle
942 ioeGetHandle (IOException (IOError h _ _ _ _)) = h
943 ioeGetHandle (UserError _) = Nothing
944 ioeGetHandle _ = error "IO.ioeGetHandle: not an IO error"
946 ioeGetErrorString (IOException (IOError _ iot _ str _)) =
950 ioeGetErrorString (UserError str) = str
951 ioeGetErrorString _ = error "IO.ioeGetErrorString: not an IO error"
953 ioeGetFileName (IOException (IOError _ _ _ _ fn)) = fn
954 ioeGetFileName (UserError _) = Nothing
955 ioeGetFileName _ = error "IO.ioeGetFileName: not an IO error"
958 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
959 PrelMain.mainIO) and report them - topHandler is the exception
960 handler they should use for this:
963 -- make sure we handle errors while reporting the error!
964 -- (e.g. evaluating the string passed to 'error' might generate
965 -- another error, etc.)
966 topHandler :: Bool -> Exception -> IO ()
967 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
969 real_handler :: Bool -> Exception -> IO ()
970 real_handler bombOut ex =
972 AsyncException StackOverflow -> reportStackOverflow bombOut
973 ErrorCall s -> reportError bombOut s
974 other -> reportError bombOut (showsPrec 0 other "\n")
976 reportStackOverflow :: Bool -> IO ()
977 reportStackOverflow bombOut = do
978 (hFlush stdout) `catchException` (\ _ -> return ())
979 callStackOverflowHook
985 reportError :: Bool -> String -> IO ()
986 reportError bombOut str = do
987 (hFlush stdout) `catchException` (\ _ -> return ())
988 let bs@(ByteArray _ len _) = packString str
989 writeErrString addrOf_ErrorHdrHook bs len
995 foreign import ccall "addrOf_ErrorHdrHook" unsafe
996 addrOf_ErrorHdrHook :: Addr
998 foreign import ccall "writeErrString__" unsafe
999 writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1001 -- SUP: Are the hooks allowed to re-enter Haskell land? If yes, remove the unsafe below.
1002 foreign import ccall "stackOverflow" unsafe
1003 callStackOverflowHook :: IO ()
1005 foreign import ccall "stg_exit" unsafe
1006 stg_exit :: Int -> IO ()
1010 A number of operations want to get at a readable or writeable handle, and fail
1014 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1015 wantReadableHandle fun handle act =
1016 withHandle_ handle $ \ handle_ -> do
1017 case haType__ handle_ of
1018 ClosedHandle -> ioe_closedHandle fun handle
1019 SemiClosedHandle -> ioe_closedHandle fun handle
1020 AppendHandle -> ioException not_readable_error
1021 WriteHandle -> ioException not_readable_error
1024 not_readable_error =
1025 IOError (Just handle) IllegalOperation fun
1026 "handle is not open for reading" Nothing
1028 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1029 wantWriteableHandle fun handle act =
1030 withHandle_ handle $ \ handle_ ->
1031 checkWriteableHandle fun handle handle_ (act handle_)
1033 wantWriteableHandle_ :: String -> Handle -> (Handle__ -> IO (Handle__, a)) -> IO a
1034 wantWriteableHandle_ fun handle act =
1035 withHandle handle $ \ handle_ ->
1036 checkWriteableHandle fun handle handle_ (act handle_)
1038 checkWriteableHandle fun handle handle_ act
1039 = case haType__ handle_ of
1040 ClosedHandle -> ioe_closedHandle fun handle
1041 SemiClosedHandle -> ioe_closedHandle fun handle
1042 ReadHandle -> ioException not_writeable_error
1045 not_writeable_error =
1046 IOError (Just handle) IllegalOperation fun
1047 "handle is not open for writing" Nothing
1049 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1050 wantRWHandle fun handle act =
1051 withHandle_ handle $ \ handle_ -> do
1052 case haType__ handle_ of
1053 ClosedHandle -> ioe_closedHandle fun handle
1054 SemiClosedHandle -> ioe_closedHandle fun handle
1057 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1058 wantSeekableHandle fun handle act =
1059 withHandle_ handle $ \ handle_ -> do
1060 case haType__ handle_ of
1061 ClosedHandle -> ioe_closedHandle fun handle
1062 SemiClosedHandle -> ioe_closedHandle fun handle
1066 Internal function for creating an @IOError@ representing the
1067 access to a closed file.
1070 ioe_closedHandle :: String -> Handle -> IO a
1071 ioe_closedHandle fun h = ioException (IOError (Just h) IllegalOperation fun
1072 "handle is closed" Nothing)
1075 Internal helper functions for Concurrent Haskell implementation
1079 mayBlock :: FILE_OBJECT -> IO Int -> IO Int
1080 mayBlock fo act = do
1083 -5 -> do -- (possibly blocking) read
1086 mayBlock fo act -- input available, re-try
1087 -6 -> do -- (possibly blocking) write
1090 mayBlock fo act -- output possible
1091 -7 -> do -- (possibly blocking) write on connected handle
1092 fd <- getConnFileFd fo
1094 mayBlock fo act -- output possible
1103 mayBlockRead :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1104 mayBlockRead fname handle fn = do
1105 r <- wantReadableHandle fname handle $ \ handle_ -> do
1106 let fo = haFO__ handle_
1109 -5 -> do -- (possibly blocking) read
1111 return (BlockRead fd)
1112 -6 -> do -- (possibly blocking) write
1114 return (BlockWrite fd)
1115 -7 -> do -- (possibly blocking) write on connected handle
1116 fd <- getConnFileFd fo
1117 return (BlockWrite fd)
1120 then return (NoBlock rc)
1121 else constructErrorAndFail fname
1125 mayBlockRead fname handle fn
1128 mayBlockRead fname handle fn
1129 NoBlock c -> return c
1131 mayBlockRead' :: String -> Handle
1132 -> (FILE_OBJECT -> IO Int)
1133 -> (FILE_OBJECT -> Int -> IO a)
1135 mayBlockRead' fname handle fn io = do
1136 r <- wantReadableHandle fname handle $ \ handle_ -> do
1137 let fo = haFO__ handle_
1140 -5 -> do -- (possibly blocking) read
1142 return (BlockRead fd)
1143 -6 -> do -- (possibly blocking) write
1145 return (BlockWrite fd)
1146 -7 -> do -- (possibly blocking) write on connected handle
1147 fd <- getConnFileFd fo
1148 return (BlockWrite fd)
1151 then do a <- io fo rc
1153 else constructErrorAndFail fname
1157 mayBlockRead' fname handle fn io
1160 mayBlockRead' fname handle fn io
1161 NoBlock c -> return c
1163 mayBlockWrite :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1164 mayBlockWrite fname handle fn = do
1165 r <- wantWriteableHandle fname handle $ \ handle_ -> do
1166 let fo = haFO__ handle_
1169 -5 -> do -- (possibly blocking) read
1171 return (BlockRead fd)
1172 -6 -> do -- (possibly blocking) write
1174 return (BlockWrite fd)
1175 -7 -> do -- (possibly blocking) write on connected handle
1176 fd <- getConnFileFd fo
1177 return (BlockWrite fd)
1180 then return (NoBlock rc)
1181 else constructErrorAndFail fname
1185 mayBlockWrite fname handle fn
1188 mayBlockWrite fname handle fn
1189 NoBlock c -> return c
1192 Foreign import declarations of helper functions:
1197 type Bytes = PrimByteArray RealWorld
1199 type Bytes = ByteArray#
1202 foreign import "libHS_cbits" "inputReady" unsafe
1203 inputReady :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1204 foreign import "libHS_cbits" "fileGetc" unsafe
1205 fileGetc :: FILE_OBJECT -> IO Int
1206 foreign import "libHS_cbits" "fileLookAhead" unsafe
1207 fileLookAhead :: FILE_OBJECT -> IO Int
1208 foreign import "libHS_cbits" "readBlock" unsafe
1209 readBlock :: FILE_OBJECT -> IO Int
1210 foreign import "libHS_cbits" "readLine" unsafe
1211 readLine :: FILE_OBJECT -> IO Int
1212 foreign import "libHS_cbits" "readChar" unsafe
1213 readChar :: FILE_OBJECT -> IO Int
1214 foreign import "libHS_cbits" "writeFileObject" unsafe
1215 writeFileObject :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1216 foreign import "libHS_cbits" "filePutc" unsafe
1217 filePutc :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1218 foreign import "libHS_cbits" "write_" unsafe
1219 write_ :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1220 foreign import "libHS_cbits" "getBufStart" unsafe
1221 getBufStart :: FILE_OBJECT -> Int -> IO Addr
1222 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1223 getWriteableBuf :: FILE_OBJECT -> IO Addr
1224 foreign import "libHS_cbits" "getBuf" unsafe
1225 getBuf :: FILE_OBJECT -> IO Addr
1226 foreign import "libHS_cbits" "getBufWPtr" unsafe
1227 getBufWPtr :: FILE_OBJECT -> IO Int
1228 foreign import "libHS_cbits" "setBufWPtr" unsafe
1229 setBufWPtr :: FILE_OBJECT -> Int -> IO ()
1230 foreign import "libHS_cbits" "closeFile" unsafe
1231 closeFile :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1232 foreign import "libHS_cbits" "fileEOF" unsafe
1233 fileEOF :: FILE_OBJECT -> IO Int{-ret code-}
1234 foreign import "libHS_cbits" "setBuffering" unsafe
1235 setBuffering :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1236 foreign import "libHS_cbits" "flushFile" unsafe
1237 flushFile :: FILE_OBJECT -> IO Int{-ret code-}
1238 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1239 flushConnectedBuf :: FILE_OBJECT -> IO ()
1240 foreign import "libHS_cbits" "getBufferMode" unsafe
1241 getBufferMode :: FILE_OBJECT -> IO Int{-ret code-}
1243 foreign import "libHS_cbits" "seekFile_int64" unsafe
1244 seekFile :: FILE_OBJECT -> Int -> Int64 -> IO Int
1246 foreign import "libHS_cbits" "seekFile" unsafe
1247 seekFile :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1250 foreign import "libHS_cbits" "seekFileP" unsafe
1251 seekFileP :: FILE_OBJECT -> IO Int{-ret code-}
1252 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1253 setTerminalEcho :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1254 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1255 getTerminalEcho :: FILE_OBJECT -> IO Int{-ret code-}
1256 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1257 isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1258 foreign import "libHS_cbits" "setConnectedTo" unsafe
1259 setConnectedTo :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1260 foreign import "libHS_cbits" "ungetChar" unsafe
1261 ungetChar :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1262 foreign import "libHS_cbits" "readChunk" unsafe
1263 readChunk :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1264 foreign import "libHS_cbits" "getFileFd" unsafe
1265 getFileFd :: FILE_OBJECT -> IO Int{-fd-}
1267 foreign import "libHS_cbits" "fileSize_int64" unsafe
1268 fileSize_int64 :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1270 foreign import "libHS_cbits" "fileSize" unsafe
1271 fileSize :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1274 foreign import "libHS_cbits" "getFilePosn" unsafe
1275 getFilePosn :: FILE_OBJECT -> IO Int
1276 foreign import "libHS_cbits" "setFilePosn" unsafe
1277 setFilePosn :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1278 foreign import "libHS_cbits" "getConnFileFd" unsafe
1279 getConnFileFd :: FILE_OBJECT -> IO Int{-fd-}
1280 foreign import "libHS_cbits" "getLock" unsafe
1281 getLock :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1282 foreign import "libHS_cbits" "openStdFile" unsafe
1283 openStdFile :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1284 foreign import "libHS_cbits" "openFile" unsafe
1285 primOpenFile :: ByteArray Int{-CString-}
1288 -> IO Addr {-file obj-}
1289 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1292 foreign import "libHS_cbits" "setBinaryMode__" unsafe
1293 setBinaryMode :: FILE_OBJECT -> Int -> IO Int