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 -fcompiling-prelude -fno-implicit-prelude -#include "cbits/stgio.h" #-}
12 #include "cbits/stgerror.h"
14 #ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
15 module PrelHandle where
19 import PrelAddr ( Addr, nullAddr )
20 import PrelByteArr ( ByteArray(..), MutableByteArray(..) )
21 import PrelRead ( Read )
22 import PrelList ( span )
25 import PrelMaybe ( Maybe(..) )
27 import PrelNum ( toBig, Integer(..), Num(..) )
29 import PrelAddr ( Addr, nullAddr )
30 import PrelReal ( toInteger )
31 import PrelPack ( packString )
32 #ifndef __PARALLEL_HASKELL__
33 import PrelWeak ( addForeignFinalizer )
38 #ifndef __PARALLEL_HASKELL__
39 import PrelForeign ( makeForeignObj, mkForeignObj )
42 #endif /* ndef(__HUGS__) */
45 #define __CONCURRENT_HASKELL__
49 #ifndef __PARALLEL_HASKELL__
50 #define FILE_OBJECT ForeignObj
52 #define FILE_OBJECT Addr
56 %*********************************************************
58 \subsection{Types @Handle@, @Handle__@}
60 %*********************************************************
62 The @Handle@ and @Handle__@ types are defined in @IOBase@.
65 {-# INLINE newHandle #-}
66 newHandle :: Handle__ -> IO Handle
68 -- Use MVars for concurrent Haskell
69 newHandle hc = newMVar hc >>= \ h ->
73 %*********************************************************
75 \subsection{@withHandle@ operations}
77 %*********************************************************
79 In the concurrent world, handles are locked during use. This is done
80 by wrapping an MVar around the handle which acts as a mutex over
81 operations on the handle.
83 To avoid races, we use the following bracketing operations. The idea
84 is to obtain the lock, do some operation and replace the lock again,
85 whether the operation succeeded or failed. We also want to handle the
86 case where the thread receives an exception while processing the IO
87 operation: in these cases we also want to relinquish the lock.
89 There are three versions of @withHandle@: corresponding to the three
90 possible combinations of:
92 - the operation may side-effect the handle
93 - the operation may return a result
95 If the operation generates an error or an exception is raised, the
96 orignal handle is always replaced [ this is the case at the moment,
97 but we might want to revisit this in the future --SDM ].
100 withHandle :: Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
101 {-# INLINE withHandle #-}
102 withHandle (Handle h) act =
103 blockAsyncExceptions $ do
105 (h',v) <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
109 withHandle_ :: Handle -> (Handle__ -> IO a) -> IO a
110 {-# INLINE withHandle_ #-}
111 withHandle_ (Handle h) act =
112 blockAsyncExceptions $ do
114 v <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
118 withHandle__ :: Handle -> (Handle__ -> IO Handle__) -> IO ()
119 {-# INLINE withHandle__ #-}
120 withHandle__ (Handle h) act =
121 blockAsyncExceptions $ do
123 h' <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
128 nullFile__ is only used for closed handles, plugging it in as a null
129 file object reference.
132 nullFile__ :: FILE_OBJECT
134 #ifndef __PARALLEL_HASKELL__
135 unsafePerformIO (makeForeignObj nullAddr (return ()))
141 mkClosedHandle__ :: Handle__
143 Handle__ { haFO__ = nullFile__,
144 haType__ = ClosedHandle,
145 haBufferMode__ = NoBuffering,
146 haFilePath__ = "closed file",
150 mkErrorHandle__ :: IOError -> Handle__
151 mkErrorHandle__ ioe =
152 Handle__ { haFO__ = nullFile__,
153 haType__ = (ErrorHandle ioe),
154 haBufferMode__ = NoBuffering,
155 haFilePath__ = "error handle",
160 %*********************************************************
162 \subsection{Handle Finalizers}
164 %*********************************************************
167 stdHandleFinalizer :: Handle -> IO ()
168 stdHandleFinalizer (Handle hdl) = do
169 handle <- takeMVar hdl
170 let fo = haFO__ handle
172 freeBuffers (haBuffers__ handle)
174 handleFinalizer :: Handle -> IO ()
175 handleFinalizer (Handle hdl) = do
176 handle <- takeMVar hdl
177 let fo = haFO__ handle
179 freeBuffers (haBuffers__ handle)
181 freeBuffers [] = return ()
182 freeBuffers (b:bs) = do { free b; freeBuffers bs }
184 foreign import "libHS_cbits" "freeStdFileObject" unsafe
185 freeStdFileObject :: FILE_OBJECT -> IO ()
186 foreign import "libHS_cbits" "freeFileObject" unsafe
187 freeFileObject :: FILE_OBJECT -> IO ()
188 foreign import "free" unsafe
189 free :: Addr -> IO ()
192 %*********************************************************
194 \subsection[StdHandles]{Standard handles}
196 %*********************************************************
198 Three handles are allocated during program initialisation. The first
199 two manage input or output from the Haskell program's standard input
200 or output channel respectively. The third manages output to the
201 standard error channel. These handles are initially open.
205 stdin, stdout, stderr :: Handle
207 stdout = unsafePerformIO (do
208 rc <- getLock (1::Int) (1::Int) -- ConcHask: SAFE, won't block
210 0 -> newHandle (mkClosedHandle__)
212 fo <- openStdFile (1::Int)
213 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
215 #ifndef __PARALLEL_HASKELL__
216 fo <- mkForeignObj fo
217 -- I know this is deprecated, but I couldn't bring myself
218 -- to move fixIO into the prelude just so I could use makeForeignObj.
223 /* I dont care what the Haskell report says, in an interactive system,
224 * stdout should be unbuffered by default.
228 (bm, bf_size) <- getBMode__ fo
229 mkBuffer__ fo bf_size
231 hdl <- newHandle (Handle__ fo WriteHandle bm "stdout" [])
233 #ifndef __PARALLEL_HASKELL__
234 addForeignFinalizer fo (stdHandleFinalizer hdl)
238 _ -> do ioError <- constructError "stdout"
239 newHandle (mkErrorHandle__ ioError)
242 stdin = unsafePerformIO (do
243 rc <- getLock (0::Int) (0::Int) -- ConcHask: SAFE, won't block
245 0 -> newHandle (mkClosedHandle__)
247 fo <- openStdFile (0::Int)
248 (1::Int){-readable-} -- ConcHask: SAFE, won't block
250 #ifndef __PARALLEL_HASKELL__
251 fo <- mkForeignObj fo
253 (bm, bf_size) <- getBMode__ fo
254 mkBuffer__ fo bf_size
255 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin" [])
256 -- when stdin and stdout are both connected to a terminal, ensure
257 -- that anything buffered on stdout is flushed prior to reading from
259 #ifndef __PARALLEL_HASKELL__
260 addForeignFinalizer fo (stdHandleFinalizer hdl)
262 hConnectTerms stdout hdl
264 _ -> do ioError <- constructError "stdin"
265 newHandle (mkErrorHandle__ ioError)
269 stderr = unsafePerformIO (do
270 rc <- getLock (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
272 0 -> newHandle (mkClosedHandle__)
274 fo <- openStdFile (2::Int)
275 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
277 #ifndef __PARALLEL_HASKELL__
278 fo <- mkForeignObj fo
280 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr" [])
281 -- when stderr and stdout are both connected to a terminal, ensure
282 -- that anything buffered on stdout is flushed prior to writing to
284 #ifndef __PARALLEL_HASKELL__
285 addForeignFinalizer fo (stdHandleFinalizer hdl)
287 hConnectTo stdout hdl
290 _ -> do ioError <- constructError "stderr"
291 newHandle (mkErrorHandle__ ioError)
295 %*********************************************************
297 \subsection[OpeningClosing]{Opening and Closing Files}
299 %*********************************************************
302 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
303 deriving (Eq, Ord, Ix, Enum, Read, Show)
308 deriving (Eq, Read, Show)
310 openFile :: FilePath -> IOMode -> IO Handle
311 openFile fp im = openFileEx fp (TextMode im)
313 openFileEx :: FilePath -> IOModeEx -> IO Handle
316 fo <- primOpenFile (packString f)
318 (binary::Int) -- ConcHask: SAFE, won't block
319 if fo /= nullAddr then do
320 #ifndef __PARALLEL_HASKELL__
321 fo <- mkForeignObj fo
323 (bm, bf_size) <- getBMode__ fo
324 mkBuffer__ fo bf_size
325 hdl <- newHandle (Handle__ fo htype bm f [])
326 #ifndef __PARALLEL_HASKELL__
327 addForeignFinalizer fo (handleFinalizer hdl)
331 constructErrorAndFailWithInfo "openFile" f
335 BinaryMode bmo -> (bmo, 1)
336 TextMode tmo -> (tmo, 0)
346 ReadMode -> ReadHandle
347 WriteMode -> WriteHandle
348 AppendMode -> AppendHandle
349 ReadWriteMode -> ReadWriteHandle
352 Computation $openFile file mode$ allocates and returns a new, open
353 handle to manage the file {\em file}. It manages input if {\em mode}
354 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
355 and both input and output if mode is $ReadWriteMode$.
357 If the file does not exist and it is opened for output, it should be
358 created as a new file. If {\em mode} is $WriteMode$ and the file
359 already exists, then it should be truncated to zero length. The
360 handle is positioned at the end of the file if {\em mode} is
361 $AppendMode$, and otherwise at the beginning (in which case its
362 internal position is 0).
364 Implementations should enforce, locally to the Haskell process,
365 multiple-reader single-writer locking on files, which is to say that
366 there may either be many handles on the same file which manage input,
367 or just one handle on the file which manages output. If any open or
368 semi-closed handle is managing a file for output, no new handle can be
369 allocated for that file. If any open or semi-closed handle is
370 managing a file for input, new handles can only be allocated if they
371 do not manage output.
373 Two files are the same if they have the same absolute name. An
374 implementation is free to impose stricter conditions.
377 hClose :: Handle -> IO ()
380 withHandle__ handle $ \ handle_ -> do
381 case haType__ handle_ of
382 ErrorHandle theError -> ioError theError
383 ClosedHandle -> return handle_
385 rc <- closeFile (haFO__ handle_)
386 (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
387 {- We explicitly close a file object so that we can be told
388 if there were any errors. Note that after @hClose@
389 has been performed, the ForeignObj embedded in the Handle
390 is still lying around in the heap, so care is taken
391 to avoid closing the file object when the ForeignObj
392 is finalized. (we overwrite the file ptr in the underlying
393 FileObject with a NULL as part of closeFile())
396 then return (handle_{ haType__ = ClosedHandle,
397 haFO__ = nullFile__ })
398 else constructErrorAndFail "hClose"
402 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
403 computation finishes, any items buffered for output and not already
404 sent to the operating system are flushed as for $flush$.
406 %*********************************************************
408 \subsection[FileSize]{Detecting the size of a file}
410 %*********************************************************
413 For a handle {\em hdl} which attached to a physical file, $hFileSize
414 hdl$ returns the size of {\em hdl} in terms of the number of items
415 which can be read from {\em hdl}.
418 hFileSize :: Handle -> IO Integer
420 withHandle_ handle $ \ handle_ -> do
421 case haType__ handle_ of
422 ErrorHandle theError -> ioError theError
423 ClosedHandle -> ioe_closedHandle "hFileSize" handle
424 SemiClosedHandle -> ioe_closedHandle "hFileSize" handle
427 mem <- primNewByteArray 8{-sizeof_int64-}
428 rc <- fileSize_int64 (haFO__ handle_) mem -- ConcHask: SAFE, won't block
430 result <- primReadInt64Array mem 0
431 return (primInt64ToInteger result)
433 constructErrorAndFail "hFileSize"
436 -- HACK! We build a unique MP_INT of the right shape to hold
437 -- a single unsigned word, and we let the C routine
438 -- change the data bits
440 case int2Integer# 1# of
442 rc <- fileSize (haFO__ handle_) d -- ConcHask: SAFE, won't block
443 if rc == (0::Int) then
446 constructErrorAndFail "hFileSize"
450 %*********************************************************
452 \subsection[EOF]{Detecting the End of Input}
454 %*********************************************************
457 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
458 @True@ if no further input can be taken from @hdl@ or for a
459 physical file, if the current I/O position is equal to the length of
460 the file. Otherwise, it returns @False@.
463 hIsEOF :: Handle -> IO Bool
465 rc <- mayBlockRead "hIsEOF" handle fileEOF
469 _ -> constructErrorAndFail "hIsEOF"
475 %*********************************************************
477 \subsection[Buffering]{Buffering Operations}
479 %*********************************************************
481 Three kinds of buffering are supported: line-buffering,
482 block-buffering or no-buffering. See @IOBase@ for definition
483 and further explanation of what the type represent.
485 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
486 handle {\em hdl} on subsequent reads and writes.
490 If {\em mode} is @LineBuffering@, line-buffering should be
493 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
494 should be enabled if possible. The size of the buffer is {\em n} items
495 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
497 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
500 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
501 to @NoBuffering@, then any items in the output buffer are written to
502 the device, and any items in the input buffer are discarded. The
503 default buffering mode when a handle is opened is
504 implementation-dependent and may depend on the object which is
505 attached to that handle.
508 hSetBuffering :: Handle -> BufferMode -> IO ()
510 hSetBuffering handle mode =
512 BlockBuffering (Just n)
514 (IOError (Just handle)
517 ("illegal buffer size " ++ showsPrec 9 n [])) -- 9 => should be parens'ified.
519 withHandle__ handle $ \ handle_ -> do
520 case haType__ handle_ of
521 ErrorHandle theError -> ioError theError
522 ClosedHandle -> ioe_closedHandle "hSetBuffering" handle
525 - we flush the old buffer regardless of whether
526 the new buffer could fit the contents of the old buffer
528 - allow a handle's buffering to change even if IO has
529 occurred (ANSI C spec. does not allow this, nor did
530 the previous implementation of IO.hSetBuffering).
531 - a non-standard extension is to allow the buffering
532 of semi-closed handles to change [sof 6/98]
534 let fo = haFO__ handle_
535 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
538 return (handle_{ haBufferMode__ = mode })
540 -- Note: failure to change the buffer size will cause old buffer to be flushed.
541 constructErrorAndFail "hSetBuffering"
547 BlockBuffering Nothing -> -2
548 BlockBuffering (Just n) -> n
551 The action @hFlush hdl@ causes any items buffered for output
552 in handle {\em hdl} to be sent immediately to the operating
556 hFlush :: Handle -> IO ()
558 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
559 let fo = haFO__ handle_
560 rc <- mayBlock fo (flushFile fo) -- ConcHask: UNSAFE, may block
564 constructErrorAndFail "hFlush"
569 %*********************************************************
571 \subsection[Seeking]{Repositioning Handles}
573 %*********************************************************
578 Handle -- Q: should this be a weak or strong ref. to the handle?
579 -- [what's the winning argument for it not being strong? --sof]
582 instance Eq HandlePosn where
583 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
585 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
586 -- We represent it as an Integer on the Haskell side, but
587 -- cheat slightly in that hGetPosn calls upon a C helper
588 -- that reports the position back via (merely) an Int.
589 type HandlePosition = Integer
591 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
592 mkHandlePosn h p = HandlePosn h p
594 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
595 deriving (Eq, Ord, Ix, Enum, Read, Show)
598 Computation @hGetPosn hdl@ returns the current I/O
599 position of {\em hdl} as an abstract position. Computation
600 $hSetPosn p$ sets the position of {\em hdl}
601 to a previously obtained position {\em p}.
604 hGetPosn :: Handle -> IO HandlePosn
606 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
607 posn <- getFilePosn (haFO__ handle_) -- ConcHask: SAFE, won't block
608 if posn /= -1 then do
609 return (mkHandlePosn handle (fromInt posn))
611 constructErrorAndFail "hGetPosn"
613 hSetPosn :: HandlePosn -> IO ()
614 hSetPosn (HandlePosn handle i@(S# _)) = hSetPosn (HandlePosn handle (toBig i))
615 hSetPosn (HandlePosn handle (J# s# d#)) =
616 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do
617 -- not as silly as it looks: the handle may have been closed in the meantime.
618 let fo = haFO__ handle_
619 rc <- mayBlock fo (setFilePosn fo (I# s#) d#) -- ConcHask: UNSAFE, may block
623 constructErrorAndFail "hSetPosn"
626 The action @hSeek hdl mode i@ sets the position of handle
627 @hdl@ depending on @mode@. If @mode@ is
629 * AbsoluteSeek - The position of @hdl@ is set to @i@.
630 * RelativeSeek - The position of @hdl@ is set to offset @i@ from
631 the current position.
632 * SeekFromEnd - The position of @hdl@ is set to offset @i@ from
635 Some handles may not be seekable (see @hIsSeekable@), or only
636 support a subset of the possible positioning operations (e.g. it may
637 only be possible to seek to the end of a tape, or to a positive
638 offset from the beginning or current position).
640 It is not possible to set a negative I/O position, or for a physical
641 file, an I/O position beyond the current end-of-file.
644 - when seeking using @SeekFromEnd@, positive offsets (>=0) means
645 seeking at or past EOF.
646 - relative seeking on buffered handles can lead to non-obvious results.
649 hSeek :: Handle -> SeekMode -> Integer -> IO ()
651 hSeek handle mode offset =
652 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
653 let fo = haFO__ handle_
654 rc <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
656 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
657 hSeek handle mode (J# s# d#) =
658 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
659 let fo = haFO__ handle_
660 rc <- mayBlock fo (seekFile fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
665 constructErrorAndFail "hSeek"
668 whence = case mode of
674 %*********************************************************
676 \subsection[Query]{Handle Properties}
678 %*********************************************************
680 A number of operations return information about the properties of a
681 handle. Each of these operations returns $True$ if the
682 handle has the specified property, and $False$
685 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
686 {\em hdl} is not block-buffered. Otherwise it returns
687 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
688 $( Just n )$ for block-buffering of {\em n} bytes.
691 hIsOpen :: Handle -> IO Bool
693 withHandle_ handle $ \ handle_ -> do
694 case haType__ handle_ of
695 ErrorHandle theError -> ioError theError
696 ClosedHandle -> return False
697 SemiClosedHandle -> return False
700 hIsClosed :: Handle -> IO Bool
702 withHandle_ handle $ \ handle_ -> do
703 case haType__ handle_ of
704 ErrorHandle theError -> ioError theError
705 ClosedHandle -> return True
708 {- not defined, nor exported, but mentioned
709 here for documentation purposes:
711 hSemiClosed :: Handle -> IO Bool
715 return (not (ho || hc))
718 hIsReadable :: Handle -> IO Bool
720 withHandle_ handle $ \ handle_ -> do
721 case haType__ handle_ of
722 ErrorHandle theError -> ioError theError
723 ClosedHandle -> ioe_closedHandle "hIsReadable" handle
724 SemiClosedHandle -> ioe_closedHandle "hIsReadable" handle
725 htype -> return (isReadable htype)
727 isReadable ReadHandle = True
728 isReadable ReadWriteHandle = True
731 hIsWritable :: Handle -> IO Bool
733 withHandle_ handle $ \ handle_ -> do
734 case haType__ handle_ of
735 ErrorHandle theError -> ioError theError
736 ClosedHandle -> ioe_closedHandle "hIsWritable" handle
737 SemiClosedHandle -> ioe_closedHandle "hIsWritable" handle
738 htype -> return (isWritable htype)
740 isWritable AppendHandle = True
741 isWritable WriteHandle = True
742 isWritable ReadWriteHandle = True
746 getBMode__ :: FILE_OBJECT -> IO (BufferMode, Int)
748 rc <- getBufferMode fo -- ConcHask: SAFE, won't block
750 0 -> return (NoBuffering, 0)
751 -1 -> return (LineBuffering, default_buffer_size)
752 -2 -> return (BlockBuffering Nothing, default_buffer_size)
753 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
754 n -> return (BlockBuffering (Just n), n)
756 default_buffer_size :: Int
757 default_buffer_size = const_BUFSIZ
760 Querying how a handle buffers its data:
763 hGetBuffering :: Handle -> IO BufferMode
764 hGetBuffering handle =
765 withHandle_ handle $ \ handle_ -> do
766 case haType__ handle_ of
767 ErrorHandle theError -> ioError theError
768 ClosedHandle -> ioe_closedHandle "hGetBuffering" handle
771 We're being non-standard here, and allow the buffering
772 of a semi-closed handle to be queried. -- sof 6/98
774 return (haBufferMode__ handle_) -- could be stricter..
778 hIsSeekable :: Handle -> IO Bool
780 withHandle_ handle $ \ handle_ -> do
781 case haType__ handle_ of
782 ErrorHandle theError -> ioError theError
783 ClosedHandle -> ioe_closedHandle "hIsSeekable" handle
784 SemiClosedHandle -> ioe_closedHandle "hIsSeekable" handle
785 AppendHandle -> return False
787 rc <- seekFileP (haFO__ handle_) -- ConcHask: SAFE, won't block
791 _ -> constructErrorAndFail "hIsSeekable"
795 %*********************************************************
797 \subsection{Changing echo status}
799 %*********************************************************
801 Non-standard GHC extension is to allow the echoing status
802 of a handles connected to terminals to be reconfigured:
805 hSetEcho :: Handle -> Bool -> IO ()
806 hSetEcho handle on = do
807 isT <- hIsTerminalDevice handle
811 withHandle_ handle $ \ handle_ -> do
812 case haType__ handle_ of
813 ErrorHandle theError -> ioError theError
814 ClosedHandle -> ioe_closedHandle "hSetEcho" handle
816 rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0) -- ConcHask: SAFE, won't block
819 else constructErrorAndFail "hSetEcho"
821 hGetEcho :: Handle -> IO Bool
823 isT <- hIsTerminalDevice handle
827 withHandle_ handle $ \ handle_ -> do
828 case haType__ handle_ of
829 ErrorHandle theError -> ioError theError
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 ErrorHandle theError -> ioError theError
843 ClosedHandle -> ioe_closedHandle "hIsTerminalDevice" handle
845 rc <- isTerminalDevice (haFO__ handle_) -- ConcHask: SAFE, won't block
849 _ -> constructErrorAndFail "hIsTerminalDevice"
853 hConnectTerms :: Handle -> Handle -> IO ()
854 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
856 hConnectTo :: Handle -> Handle -> IO ()
857 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
859 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
860 hConnectHdl_ hW hR is_tty =
861 wantRWHandle "hConnectTo" hW $ \ hW_ ->
862 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
863 setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
866 As an extension, we also allow characters to be pushed back.
867 Like ANSI C stdio, we guarantee no more than one character of
868 pushback. (For unbuffered channels, the (default) push-back limit is
872 hUngetChar :: Handle -> Char -> IO ()
873 hUngetChar handle c =
874 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
875 rc <- ungetChar (haFO__ handle_) c -- ConcHask: SAFE, won't block
877 then constructErrorAndFail "hUngetChar"
883 Hoisting files in in one go is sometimes useful, so we support
884 this as an extension:
887 -- in one go, read file into an externally allocated buffer.
888 slurpFile :: FilePath -> IO (Addr, Int)
890 handle <- openFile fname ReadMode
891 sz <- hFileSize handle
892 if sz > toInteger (maxBound::Int) then
893 ioError (userError "slurpFile: file too big")
895 let sz_i = fromInteger sz
896 chunk <- allocMemory__ sz_i
900 constructErrorAndFail "slurpFile"
902 rc <- withHandle_ handle ( \ handle_ -> do
903 let fo = haFO__ handle_
904 mayBlock fo (readChunk fo chunk 0 sz_i) -- ConcHask: UNSAFE, may block.
908 then constructErrorAndFail "slurpFile"
909 else return (chunk, rc)
913 Sometimes it's useful to get at the file descriptor that
914 the Handle contains..
917 getHandleFd :: Handle -> IO Int
919 withHandle_ handle $ \ handle_ -> do
920 case (haType__ handle_) of
921 ErrorHandle theError -> ioError theError
922 ClosedHandle -> ioe_closedHandle "getHandleFd" handle
924 fd <- getFileFd (haFO__ handle_)
929 %*********************************************************
931 \subsection{Miscellaneous}
933 %*********************************************************
935 These three functions are meant to get things out of @IOErrors@.
940 ioeGetFileName :: IOError -> Maybe FilePath
941 ioeGetErrorString :: IOError -> String
942 ioeGetHandle :: IOError -> Maybe Handle
944 ioeGetHandle (IOError h _ _ _) = h
945 ioeGetErrorString (IOError _ iot _ str) =
950 ioeGetFileName (IOError _ _ _ str) =
951 case span (/=':') str of
957 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
958 PrelMain.mainIO) and report them - topHandler is the exception
959 handler they should use for this:
962 -- make sure we handle errors while reporting the error!
963 -- (e.g. evaluating the string passed to 'error' might generate
964 -- another error, etc.)
965 topHandler :: Bool -> Exception -> IO ()
966 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
968 real_handler :: Bool -> Exception -> IO ()
969 real_handler bombOut ex =
971 AsyncException StackOverflow -> reportStackOverflow bombOut
972 ErrorCall s -> reportError bombOut s
973 other -> reportError bombOut (showsPrec 0 other "\n")
975 reportStackOverflow :: Bool -> IO ()
976 reportStackOverflow bombOut = do
977 (hFlush stdout) `catchException` (\ _ -> return ())
978 callStackOverflowHook
984 reportError :: Bool -> String -> IO ()
985 reportError bombOut str = do
986 (hFlush stdout) `catchException` (\ _ -> return ())
987 let bs@(ByteArray _ len _) = packString str
988 writeErrString addrOf_ErrorHdrHook bs len
994 foreign label "ErrorHdrHook"
995 addrOf_ErrorHdrHook :: Addr
997 foreign import ccall "writeErrString__" unsafe
998 writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1000 foreign import ccall "stackOverflow"
1001 callStackOverflowHook :: IO ()
1003 foreign import ccall "stg_exit"
1004 stg_exit :: Int -> IO ()
1008 A number of operations want to get at a readable or writeable handle, and fail
1012 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1013 wantReadableHandle fun handle act =
1014 withHandle_ handle $ \ handle_ -> do
1015 case haType__ handle_ of
1016 ErrorHandle theError -> ioError theError
1017 ClosedHandle -> ioe_closedHandle fun handle
1018 SemiClosedHandle -> ioe_closedHandle fun handle
1019 AppendHandle -> ioError not_readable_error
1020 WriteHandle -> ioError not_readable_error
1023 not_readable_error =
1024 IOError (Just handle) IllegalOperation fun
1025 ("handle is not open for reading")
1027 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1028 wantWriteableHandle fun handle act =
1029 withHandle_ handle $ \ handle_ ->
1030 checkWriteableHandle fun handle handle_ (act handle_)
1032 wantWriteableHandle_ :: String -> Handle -> (Handle__ -> IO (Handle__, a)) -> IO a
1033 wantWriteableHandle_ fun handle act =
1034 withHandle handle $ \ handle_ ->
1035 checkWriteableHandle fun handle handle_ (act handle_)
1037 checkWriteableHandle fun handle handle_ act
1038 = case haType__ handle_ of
1039 ErrorHandle theError -> ioError theError
1040 ClosedHandle -> ioe_closedHandle fun handle
1041 SemiClosedHandle -> ioe_closedHandle fun handle
1042 ReadHandle -> ioError not_writeable_error
1045 not_writeable_error =
1046 IOError (Just handle) IllegalOperation fun
1047 ("handle is not open for writing")
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 ErrorHandle theError -> ioError theError
1054 ClosedHandle -> ioe_closedHandle fun handle
1055 SemiClosedHandle -> ioe_closedHandle fun handle
1058 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1059 wantSeekableHandle fun handle act =
1060 withHandle_ handle $ \ handle_ -> do
1061 case haType__ handle_ of
1062 ErrorHandle theError -> ioError theError
1063 ClosedHandle -> ioe_closedHandle fun handle
1064 SemiClosedHandle -> ioe_closedHandle fun handle
1067 not_seekable_error =
1068 IOError (Just handle)
1069 IllegalOperation fun
1070 ("handle is not seekable")
1074 Internal function for creating an @IOError@ representing the
1075 access to a closed file.
1078 ioe_closedHandle :: String -> Handle -> IO a
1079 ioe_closedHandle fun h = ioError (IOError (Just h) IllegalOperation fun "handle is closed")
1082 Internal helper functions for Concurrent Haskell implementation
1086 mayBlock :: FILE_OBJECT -> IO Int -> IO Int
1087 mayBlock fo act = do
1090 -5 -> do -- (possibly blocking) read
1093 mayBlock fo act -- input available, re-try
1094 -6 -> do -- (possibly blocking) write
1097 mayBlock fo act -- output possible
1098 -7 -> do -- (possibly blocking) write on connected handle
1099 fd <- getConnFileFd fo
1101 mayBlock fo act -- output possible
1110 mayBlockRead :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1111 mayBlockRead fname handle fn = do
1112 r <- wantReadableHandle fname handle $ \ handle_ -> do
1113 let fo = haFO__ handle_
1116 -5 -> do -- (possibly blocking) read
1118 return (BlockRead fd)
1119 -6 -> do -- (possibly blocking) write
1121 return (BlockWrite fd)
1122 -7 -> do -- (possibly blocking) write on connected handle
1123 fd <- getConnFileFd fo
1124 return (BlockWrite fd)
1127 then return (NoBlock rc)
1128 else constructErrorAndFail fname
1132 mayBlockRead fname handle fn
1135 mayBlockRead fname handle fn
1136 NoBlock c -> return c
1138 mayBlockWrite :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1139 mayBlockWrite fname handle fn = do
1140 r <- wantWriteableHandle fname handle $ \ handle_ -> do
1141 let fo = haFO__ handle_
1144 -5 -> do -- (possibly blocking) read
1146 return (BlockRead fd)
1147 -6 -> do -- (possibly blocking) write
1149 return (BlockWrite fd)
1150 -7 -> do -- (possibly blocking) write on connected handle
1151 fd <- getConnFileFd fo
1152 return (BlockWrite fd)
1155 then return (NoBlock rc)
1156 else constructErrorAndFail fname
1160 mayBlockWrite fname handle fn
1163 mayBlockWrite fname handle fn
1164 NoBlock c -> return c
1167 Foreign import declarations of helper functions:
1172 type Bytes = PrimByteArray RealWorld
1174 type Bytes = ByteArray#
1177 foreign import "libHS_cbits" "inputReady" unsafe
1178 inputReady :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1179 foreign import "libHS_cbits" "fileGetc" unsafe
1180 fileGetc :: FILE_OBJECT -> IO Int
1181 foreign import "libHS_cbits" "fileLookAhead" unsafe
1182 fileLookAhead :: FILE_OBJECT -> IO Int
1183 foreign import "libHS_cbits" "readBlock" unsafe
1184 readBlock :: FILE_OBJECT -> IO Int
1185 foreign import "libHS_cbits" "readLine" unsafe
1186 readLine :: FILE_OBJECT -> IO Int
1187 foreign import "libHS_cbits" "readChar" unsafe
1188 readChar :: FILE_OBJECT -> IO Int
1189 foreign import "libHS_cbits" "writeFileObject" unsafe
1190 writeFileObject :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1191 foreign import "libHS_cbits" "filePutc" unsafe
1192 filePutc :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1193 foreign import "libHS_cbits" "write_" unsafe
1194 write_ :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1195 foreign import "libHS_cbits" "getBufStart" unsafe
1196 getBufStart :: FILE_OBJECT -> Int -> IO Addr
1197 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1198 getWriteableBuf :: FILE_OBJECT -> IO Addr
1199 foreign import "libHS_cbits" "getBuf" unsafe
1200 getBuf :: FILE_OBJECT -> IO Addr
1201 foreign import "libHS_cbits" "getBufWPtr" unsafe
1202 getBufWPtr :: FILE_OBJECT -> IO Int
1203 foreign import "libHS_cbits" "setBufWPtr" unsafe
1204 setBufWPtr :: FILE_OBJECT -> Int -> IO ()
1205 foreign import "libHS_cbits" "closeFile" unsafe
1206 closeFile :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1207 foreign import "libHS_cbits" "fileEOF" unsafe
1208 fileEOF :: FILE_OBJECT -> IO Int{-ret code-}
1209 foreign import "libHS_cbits" "setBuffering" unsafe
1210 setBuffering :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1211 foreign import "libHS_cbits" "flushFile" unsafe
1212 flushFile :: FILE_OBJECT -> IO Int{-ret code-}
1213 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1214 flushConnectedBuf :: FILE_OBJECT -> IO ()
1215 foreign import "libHS_cbits" "getBufferMode" unsafe
1216 getBufferMode :: FILE_OBJECT -> IO Int{-ret code-}
1218 foreign import "libHS_cbits" "seekFile_int64" unsafe
1219 seekFile :: FILE_OBJECT -> Int -> Int64 -> IO Int
1221 foreign import "libHS_cbits" "seekFile" unsafe
1222 seekFile :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1225 foreign import "libHS_cbits" "seekFileP" unsafe
1226 seekFileP :: FILE_OBJECT -> IO Int{-ret code-}
1227 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1228 setTerminalEcho :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1229 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1230 getTerminalEcho :: FILE_OBJECT -> IO Int{-ret code-}
1231 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1232 isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1233 foreign import "libHS_cbits" "setConnectedTo" unsafe
1234 setConnectedTo :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1235 foreign import "libHS_cbits" "ungetChar" unsafe
1236 ungetChar :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1237 foreign import "libHS_cbits" "readChunk" unsafe
1238 readChunk :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1239 foreign import "libHS_cbits" "getFileFd" unsafe
1240 getFileFd :: FILE_OBJECT -> IO Int{-fd-}
1242 foreign import "libHS_cbits" "fileSize_int64" unsafe
1243 fileSize_int64 :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1245 foreign import "libHS_cbits" "fileSize" unsafe
1246 fileSize :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1249 foreign import "libHS_cbits" "getFilePosn" unsafe
1250 getFilePosn :: FILE_OBJECT -> IO Int
1251 foreign import "libHS_cbits" "setFilePosn" unsafe
1252 setFilePosn :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1253 foreign import "libHS_cbits" "getConnFileFd" unsafe
1254 getConnFileFd :: FILE_OBJECT -> IO Int{-fd-}
1255 foreign import "libHS_cbits" "getLock" unsafe
1256 getLock :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1257 foreign import "libHS_cbits" "openStdFile" unsafe
1258 openStdFile :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1259 foreign import "libHS_cbits" "openFile" unsafe
1260 primOpenFile :: ByteArray Int{-CString-}
1263 -> IO Addr {-file obj-}
1264 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1267 foreign import "libHS_cbits" "setBinaryMode__"
1268 setBinaryMode :: FILE_OBJECT -> Int -> IO Int