1 % ------------------------------------------------------------------------------
2 % $Id: PrelHandle.lhs,v 1.63 2000/11/07 10:42:56 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 <- malloc 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 =
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 =
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 =
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",
167 %*********************************************************
169 \subsection{Handle Finalizers}
171 %*********************************************************
174 stdHandleFinalizer :: Handle -> IO ()
175 stdHandleFinalizer (Handle hdl) = do
176 handle <- takeMVar hdl
177 let fo = haFO__ handle
179 freeBuffers (haBuffers__ handle)
181 handleFinalizer :: Handle -> IO ()
182 handleFinalizer (Handle hdl) = do
183 handle <- takeMVar hdl
184 let fo = haFO__ handle
186 freeBuffers (haBuffers__ handle)
188 freeBuffers [] = return ()
189 freeBuffers (b:bs) = do { free b; freeBuffers bs }
191 foreign import "libHS_cbits" "freeStdFileObject" unsafe
192 freeStdFileObject :: FILE_OBJECT -> IO ()
193 foreign import "libHS_cbits" "freeFileObject" unsafe
194 freeFileObject :: FILE_OBJECT -> IO ()
195 foreign import "free" unsafe
196 free :: Addr -> IO ()
199 %*********************************************************
201 \subsection[StdHandles]{Standard handles}
203 %*********************************************************
205 Three handles are allocated during program initialisation. The first
206 two manage input or output from the Haskell program's standard input
207 or output channel respectively. The third manages output to the
208 standard error channel. These handles are initially open.
212 stdin, stdout, stderr :: Handle
214 stdout = unsafePerformIO (do
215 rc <- getLock (1::Int) (1::Int) -- ConcHask: SAFE, won't block
217 0 -> newHandle (mkClosedHandle__)
219 fo <- openStdFile (1::Int)
220 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
222 #ifndef __PARALLEL_HASKELL__
223 fo <- mkForeignObj fo
224 -- I know this is deprecated, but I couldn't bring myself
225 -- to move fixIO into the prelude just so I could use makeForeignObj.
230 /* I dont care what the Haskell report says, in an interactive system,
231 * stdout should be unbuffered by default.
235 (bm, bf_size) <- getBMode__ fo
236 mkBuffer__ fo bf_size
238 hdl <- newHandle (Handle__ fo WriteHandle bm "stdout" [])
240 #ifndef __PARALLEL_HASKELL__
241 addForeignFinalizer fo (stdHandleFinalizer hdl)
245 _ -> constructErrorAndFail "stdout"
248 stdin = unsafePerformIO (do
249 rc <- getLock (0::Int) (0::Int) -- ConcHask: SAFE, won't block
251 0 -> newHandle (mkClosedHandle__)
253 fo <- openStdFile (0::Int)
254 (1::Int){-readable-} -- ConcHask: SAFE, won't block
256 #ifndef __PARALLEL_HASKELL__
257 fo <- mkForeignObj fo
259 (bm, bf_size) <- getBMode__ fo
260 mkBuffer__ fo bf_size
261 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin" [])
262 -- when stdin and stdout are both connected to a terminal, ensure
263 -- that anything buffered on stdout is flushed prior to reading from
265 #ifndef __PARALLEL_HASKELL__
266 addForeignFinalizer fo (stdHandleFinalizer hdl)
268 hConnectTerms stdout hdl
270 _ -> constructErrorAndFail "stdin"
274 stderr = unsafePerformIO (do
275 rc <- getLock (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
277 0 -> newHandle (mkClosedHandle__)
279 fo <- openStdFile (2::Int)
280 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
282 #ifndef __PARALLEL_HASKELL__
283 fo <- mkForeignObj fo
285 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr" [])
286 -- when stderr and stdout are both connected to a terminal, ensure
287 -- that anything buffered on stdout is flushed prior to writing to
289 #ifndef __PARALLEL_HASKELL__
290 addForeignFinalizer fo (stdHandleFinalizer hdl)
292 hConnectTo stdout hdl
295 _ -> constructErrorAndFail "stderr"
299 %*********************************************************
301 \subsection[OpeningClosing]{Opening and Closing Files}
303 %*********************************************************
306 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
307 deriving (Eq, Ord, Ix, Enum, Read, Show)
312 deriving (Eq, Read, Show)
314 openFile :: FilePath -> IOMode -> IO Handle
315 openFile fp im = openFileEx fp (TextMode im)
317 openFileEx :: FilePath -> IOModeEx -> IO Handle
320 fo <- primOpenFile (packString f)
322 (binary::Int) -- ConcHask: SAFE, won't block
323 if fo /= nullAddr then do
324 #ifndef __PARALLEL_HASKELL__
325 fo <- mkForeignObj fo
327 (bm, bf_size) <- getBMode__ fo
328 mkBuffer__ fo bf_size
329 hdl <- newHandle (Handle__ fo htype bm f [])
330 #ifndef __PARALLEL_HASKELL__
331 addForeignFinalizer fo (handleFinalizer hdl)
335 constructErrorAndFailWithInfo "openFile" f
339 BinaryMode bmo -> (bmo, 1)
340 TextMode tmo -> (tmo, 0)
350 ReadMode -> ReadHandle
351 WriteMode -> WriteHandle
352 AppendMode -> AppendHandle
353 ReadWriteMode -> ReadWriteHandle
356 Computation $openFile file mode$ allocates and returns a new, open
357 handle to manage the file {\em file}. It manages input if {\em mode}
358 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
359 and both input and output if mode is $ReadWriteMode$.
361 If the file does not exist and it is opened for output, it should be
362 created as a new file. If {\em mode} is $WriteMode$ and the file
363 already exists, then it should be truncated to zero length. The
364 handle is positioned at the end of the file if {\em mode} is
365 $AppendMode$, and otherwise at the beginning (in which case its
366 internal position is 0).
368 Implementations should enforce, locally to the Haskell process,
369 multiple-reader single-writer locking on files, which is to say that
370 there may either be many handles on the same file which manage input,
371 or just one handle on the file which manages output. If any open or
372 semi-closed handle is managing a file for output, no new handle can be
373 allocated for that file. If any open or semi-closed handle is
374 managing a file for input, new handles can only be allocated if they
375 do not manage output.
377 Two files are the same if they have the same absolute name. An
378 implementation is free to impose stricter conditions.
381 hClose :: Handle -> IO ()
384 withHandle__ handle $ \ handle_ -> do
385 case haType__ handle_ of
386 ClosedHandle -> return handle_
388 rc <- closeFile (haFO__ handle_)
389 (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
390 {- We explicitly close a file object so that we can be told
391 if there were any errors. Note that after @hClose@
392 has been performed, the ForeignObj embedded in the Handle
393 is still lying around in the heap, so care is taken
394 to avoid closing the file object when the ForeignObj
395 is finalized. (we overwrite the file ptr in the underlying
396 FileObject with a NULL as part of closeFile())
400 then constructErrorAndFail "hClose"
402 -- free the spare buffers (except the handle buffer)
403 -- associated with this handle.
404 else do freeBuffers (haBuffers__ handle_)
405 return (handle_{ haType__ = ClosedHandle,
409 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
410 computation finishes, any items buffered for output and not already
411 sent to the operating system are flushed as for $flush$.
413 %*********************************************************
415 \subsection[FileSize]{Detecting the size of a file}
417 %*********************************************************
420 For a handle {\em hdl} which attached to a physical file, $hFileSize
421 hdl$ returns the size of {\em hdl} in terms of the number of items
422 which can be read from {\em hdl}.
425 hFileSize :: Handle -> IO Integer
427 withHandle_ handle $ \ handle_ -> do
428 case haType__ handle_ of
429 ClosedHandle -> ioe_closedHandle "hFileSize" handle
430 SemiClosedHandle -> ioe_closedHandle "hFileSize" handle
433 mem <- primNewByteArray 8{-sizeof_int64-}
434 rc <- fileSize_int64 (haFO__ handle_) mem -- ConcHask: SAFE, won't block
436 result <- primReadInt64Array mem 0
437 return (primInt64ToInteger result)
439 constructErrorAndFail "hFileSize"
442 -- HACK! We build a unique MP_INT of the right shape to hold
443 -- a single unsigned word, and we let the C routine
444 -- change the data bits
446 case int2Integer# 1# of
448 rc <- fileSize (haFO__ handle_) d -- ConcHask: SAFE, won't block
449 if rc == (0::Int) then
452 constructErrorAndFail "hFileSize"
456 %*********************************************************
458 \subsection[EOF]{Detecting the End of Input}
460 %*********************************************************
463 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
464 @True@ if no further input can be taken from @hdl@ or for a
465 physical file, if the current I/O position is equal to the length of
466 the file. Otherwise, it returns @False@.
469 hIsEOF :: Handle -> IO Bool
471 rc <- mayBlockRead "hIsEOF" handle fileEOF
475 _ -> constructErrorAndFail "hIsEOF"
481 %*********************************************************
483 \subsection[Buffering]{Buffering Operations}
485 %*********************************************************
487 Three kinds of buffering are supported: line-buffering,
488 block-buffering or no-buffering. See @IOBase@ for definition
489 and further explanation of what the type represent.
491 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
492 handle {\em hdl} on subsequent reads and writes.
496 If {\em mode} is @LineBuffering@, line-buffering should be
499 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
500 should be enabled if possible. The size of the buffer is {\em n} items
501 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
503 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
506 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
507 to @NoBuffering@, then any items in the output buffer are written to
508 the device, and any items in the input buffer are discarded. The
509 default buffering mode when a handle is opened is
510 implementation-dependent and may depend on the object which is
511 attached to that handle.
514 hSetBuffering :: Handle -> BufferMode -> IO ()
516 hSetBuffering handle mode =
518 BlockBuffering (Just n)
519 | n <= 0 -> ioException
520 (IOError (Just handle)
523 ("illegal buffer size " ++ showsPrec 9 n []))
524 -- 9 => should be parens'ified.
526 withHandle__ handle $ \ handle_ -> do
527 case haType__ handle_ of
528 ClosedHandle -> ioe_closedHandle "hSetBuffering" handle
531 - we flush the old buffer regardless of whether
532 the new buffer could fit the contents of the old buffer
534 - allow a handle's buffering to change even if IO has
535 occurred (ANSI C spec. does not allow this, nor did
536 the previous implementation of IO.hSetBuffering).
537 - a non-standard extension is to allow the buffering
538 of semi-closed handles to change [sof 6/98]
540 let fo = haFO__ handle_
541 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
544 return (handle_{ haBufferMode__ = mode })
546 -- Note: failure to change the buffer size will cause old buffer to be flushed.
547 constructErrorAndFail "hSetBuffering"
553 BlockBuffering Nothing -> -2
554 BlockBuffering (Just n) -> n
557 The action @hFlush hdl@ causes any items buffered for output
558 in handle {\em hdl} to be sent immediately to the operating
562 hFlush :: Handle -> IO ()
564 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
565 let fo = haFO__ handle_
566 rc <- mayBlock fo (flushFile fo) -- ConcHask: UNSAFE, may block
570 constructErrorAndFail "hFlush"
575 %*********************************************************
577 \subsection[Seeking]{Repositioning Handles}
579 %*********************************************************
584 Handle -- Q: should this be a weak or strong ref. to the handle?
585 -- [what's the winning argument for it not being strong? --sof]
588 instance Eq HandlePosn where
589 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
591 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
592 -- We represent it as an Integer on the Haskell side, but
593 -- cheat slightly in that hGetPosn calls upon a C helper
594 -- that reports the position back via (merely) an Int.
595 type HandlePosition = Integer
597 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
598 mkHandlePosn h p = HandlePosn h p
600 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
601 deriving (Eq, Ord, Ix, Enum, Read, Show)
604 Computation @hGetPosn hdl@ returns the current I/O
605 position of {\em hdl} as an abstract position. Computation
606 $hSetPosn p$ sets the position of {\em hdl}
607 to a previously obtained position {\em p}.
610 hGetPosn :: Handle -> IO HandlePosn
612 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
613 posn <- getFilePosn (haFO__ handle_) -- ConcHask: SAFE, won't block
614 if posn /= -1 then do
615 return (mkHandlePosn handle (fromInt posn))
617 constructErrorAndFail "hGetPosn"
619 hSetPosn :: HandlePosn -> IO ()
620 hSetPosn (HandlePosn handle i@(S# _)) = hSetPosn (HandlePosn handle (toBig i))
621 hSetPosn (HandlePosn handle (J# s# d#)) =
622 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do
623 -- not as silly as it looks: the handle may have been closed in the meantime.
624 let fo = haFO__ handle_
625 rc <- mayBlock fo (setFilePosn fo (I# s#) d#) -- ConcHask: UNSAFE, may block
629 constructErrorAndFail "hSetPosn"
632 The action @hSeek hdl mode i@ sets the position of handle
633 @hdl@ depending on @mode@. If @mode@ is
635 * AbsoluteSeek - The position of @hdl@ is set to @i@.
636 * RelativeSeek - The position of @hdl@ is set to offset @i@ from
637 the current position.
638 * SeekFromEnd - The position of @hdl@ is set to offset @i@ from
641 Some handles may not be seekable (see @hIsSeekable@), or only
642 support a subset of the possible positioning operations (e.g. it may
643 only be possible to seek to the end of a tape, or to a positive
644 offset from the beginning or current position).
646 It is not possible to set a negative I/O position, or for a physical
647 file, an I/O position beyond the current end-of-file.
650 - when seeking using @SeekFromEnd@, positive offsets (>=0) means
651 seeking at or past EOF.
652 - relative seeking on buffered handles can lead to non-obvious results.
655 hSeek :: Handle -> SeekMode -> Integer -> IO ()
657 hSeek handle mode offset =
658 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
659 let fo = haFO__ handle_
660 rc <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
662 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
663 hSeek handle mode (J# s# d#) =
664 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
665 let fo = haFO__ handle_
666 rc <- mayBlock fo (seekFile fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
671 constructErrorAndFail "hSeek"
674 whence = case mode of
680 %*********************************************************
682 \subsection[Query]{Handle Properties}
684 %*********************************************************
686 A number of operations return information about the properties of a
687 handle. Each of these operations returns $True$ if the
688 handle has the specified property, and $False$
691 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
692 {\em hdl} is not block-buffered. Otherwise it returns
693 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
694 $( Just n )$ for block-buffering of {\em n} bytes.
697 hIsOpen :: Handle -> IO Bool
699 withHandle_ handle $ \ handle_ -> do
700 case haType__ handle_ of
701 ClosedHandle -> return False
702 SemiClosedHandle -> return False
705 hIsClosed :: Handle -> IO Bool
707 withHandle_ handle $ \ handle_ -> do
708 case haType__ handle_ of
709 ClosedHandle -> return True
712 {- not defined, nor exported, but mentioned
713 here for documentation purposes:
715 hSemiClosed :: Handle -> IO Bool
719 return (not (ho || hc))
722 hIsReadable :: Handle -> IO Bool
724 withHandle_ handle $ \ handle_ -> do
725 case haType__ handle_ of
726 ClosedHandle -> ioe_closedHandle "hIsReadable" handle
727 SemiClosedHandle -> ioe_closedHandle "hIsReadable" handle
728 htype -> return (isReadable htype)
730 isReadable ReadHandle = True
731 isReadable ReadWriteHandle = True
734 hIsWritable :: Handle -> IO Bool
736 withHandle_ handle $ \ handle_ -> do
737 case haType__ handle_ of
738 ClosedHandle -> ioe_closedHandle "hIsWritable" handle
739 SemiClosedHandle -> ioe_closedHandle "hIsWritable" handle
740 htype -> return (isWritable htype)
742 isWritable AppendHandle = True
743 isWritable WriteHandle = True
744 isWritable ReadWriteHandle = True
748 getBMode__ :: FILE_OBJECT -> IO (BufferMode, Int)
750 rc <- getBufferMode fo -- ConcHask: SAFE, won't block
752 0 -> return (NoBuffering, 0)
753 -1 -> return (LineBuffering, default_buffer_size)
754 -2 -> return (BlockBuffering Nothing, default_buffer_size)
755 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
756 n -> return (BlockBuffering (Just n), n)
758 default_buffer_size :: Int
759 default_buffer_size = const_BUFSIZ
762 Querying how a handle buffers its data:
765 hGetBuffering :: Handle -> IO BufferMode
766 hGetBuffering handle =
767 withHandle_ handle $ \ handle_ -> do
768 case haType__ handle_ of
769 ClosedHandle -> ioe_closedHandle "hGetBuffering" handle
772 We're being non-standard here, and allow the buffering
773 of a semi-closed handle to be queried. -- sof 6/98
775 return (haBufferMode__ handle_) -- could be stricter..
779 hIsSeekable :: Handle -> IO Bool
781 withHandle_ handle $ \ handle_ -> do
782 case haType__ handle_ of
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 ClosedHandle -> ioe_closedHandle "hSetEcho" handle
815 rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0) -- ConcHask: SAFE, won't block
818 else constructErrorAndFail "hSetEcho"
820 hGetEcho :: Handle -> IO Bool
822 isT <- hIsTerminalDevice handle
826 withHandle_ handle $ \ handle_ -> do
827 case haType__ handle_ of
828 ClosedHandle -> ioe_closedHandle "hGetEcho" handle
830 rc <- getTerminalEcho (haFO__ handle_) -- ConcHask: SAFE, won't block
834 _ -> constructErrorAndFail "hSetEcho"
836 hIsTerminalDevice :: Handle -> IO Bool
837 hIsTerminalDevice handle = do
838 withHandle_ handle $ \ handle_ -> do
839 case haType__ handle_ of
840 ClosedHandle -> ioe_closedHandle "hIsTerminalDevice" handle
842 rc <- isTerminalDevice (haFO__ handle_) -- ConcHask: SAFE, won't block
846 _ -> constructErrorAndFail "hIsTerminalDevice"
850 hConnectTerms :: Handle -> Handle -> IO ()
851 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
853 hConnectTo :: Handle -> Handle -> IO ()
854 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
856 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
857 hConnectHdl_ hW hR is_tty =
858 wantRWHandle "hConnectTo" hW $ \ hW_ ->
859 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
860 setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
863 As an extension, we also allow characters to be pushed back.
864 Like ANSI C stdio, we guarantee no more than one character of
865 pushback. (For unbuffered channels, the (default) push-back limit is
869 hUngetChar :: Handle -> Char -> IO ()
870 hUngetChar handle c =
871 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
872 rc <- ungetChar (haFO__ handle_) c -- ConcHask: SAFE, won't block
874 then constructErrorAndFail "hUngetChar"
880 Hoisting files in in one go is sometimes useful, so we support
881 this as an extension:
884 -- in one go, read file into an externally allocated buffer.
885 slurpFile :: FilePath -> IO (Addr, Int)
887 handle <- openFile fname ReadMode
888 sz <- hFileSize handle
889 if sz > toInteger (maxBound::Int) then
890 ioError (userError "slurpFile: file too big")
892 let sz_i = fromInteger sz
897 constructErrorAndFail "slurpFile"
899 rc <- withHandle_ handle ( \ handle_ -> do
900 let fo = haFO__ handle_
901 mayBlock fo (readChunk fo chunk 0 sz_i) -- ConcHask: UNSAFE, may block.
905 then constructErrorAndFail "slurpFile"
906 else return (chunk, rc)
910 Sometimes it's useful to get at the file descriptor that
911 the Handle contains..
914 getHandleFd :: Handle -> IO Int
916 withHandle_ handle $ \ handle_ -> do
917 case (haType__ handle_) of
918 ClosedHandle -> ioe_closedHandle "getHandleFd" handle
920 fd <- getFileFd (haFO__ handle_)
925 %*********************************************************
927 \subsection{Miscellaneous}
929 %*********************************************************
931 These three functions are meant to get things out of @IOErrors@.
936 ioeGetFileName :: IOError -> Maybe FilePath
937 ioeGetErrorString :: IOError -> String
938 ioeGetHandle :: IOError -> Maybe Handle
940 ioeGetHandle (IOException (IOError h _ _ _)) = h
941 ioeGetHandle _ = error "IO.ioeGetHandle: not an IO error"
943 ioeGetErrorString (IOException (IOError _ iot _ str)) =
947 ioeGetErrorString _ = error "IO.ioeGetErrorString: not an IO error"
949 ioeGetFileName (IOException (IOError _ _ _ str)) =
950 case span (/=':') str of
953 ioeGetFileName _ = error "IO.ioeGetFileName: not an IO error"
956 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
957 PrelMain.mainIO) and report them - topHandler is the exception
958 handler they should use for this:
961 -- make sure we handle errors while reporting the error!
962 -- (e.g. evaluating the string passed to 'error' might generate
963 -- another error, etc.)
964 topHandler :: Bool -> Exception -> IO ()
965 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
967 real_handler :: Bool -> Exception -> IO ()
968 real_handler bombOut ex =
970 AsyncException StackOverflow -> reportStackOverflow bombOut
971 ErrorCall s -> reportError bombOut s
972 other -> reportError bombOut (showsPrec 0 other "\n")
974 reportStackOverflow :: Bool -> IO ()
975 reportStackOverflow bombOut = do
976 (hFlush stdout) `catchException` (\ _ -> return ())
977 callStackOverflowHook
983 reportError :: Bool -> String -> IO ()
984 reportError bombOut str = do
985 (hFlush stdout) `catchException` (\ _ -> return ())
986 let bs@(ByteArray _ len _) = packString str
987 writeErrString addrOf_ErrorHdrHook bs len
993 foreign import ccall "addrOf_ErrorHdrHook" unsafe
994 addrOf_ErrorHdrHook :: Addr
996 foreign import ccall "writeErrString__" unsafe
997 writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
999 -- SUP: Are the hooks allowed to re-enter Haskell land? If yes, remove the unsafe below.
1000 foreign import ccall "stackOverflow" unsafe
1001 callStackOverflowHook :: IO ()
1003 foreign import ccall "stg_exit" unsafe
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 ClosedHandle -> ioe_closedHandle fun handle
1017 SemiClosedHandle -> ioe_closedHandle fun handle
1018 AppendHandle -> ioException not_readable_error
1019 WriteHandle -> ioException not_readable_error
1022 not_readable_error =
1023 IOError (Just handle) IllegalOperation fun
1024 ("handle is not open for reading")
1026 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1027 wantWriteableHandle fun handle act =
1028 withHandle_ handle $ \ handle_ ->
1029 checkWriteableHandle fun handle handle_ (act handle_)
1031 wantWriteableHandle_ :: String -> Handle -> (Handle__ -> IO (Handle__, a)) -> IO a
1032 wantWriteableHandle_ fun handle act =
1033 withHandle handle $ \ handle_ ->
1034 checkWriteableHandle fun handle handle_ (act handle_)
1036 checkWriteableHandle fun handle handle_ act
1037 = case haType__ handle_ of
1038 ClosedHandle -> ioe_closedHandle fun handle
1039 SemiClosedHandle -> ioe_closedHandle fun handle
1040 ReadHandle -> ioError not_writeable_error
1043 not_writeable_error =
1044 IOException (IOError (Just handle) IllegalOperation fun
1045 ("handle is not open for writing"))
1047 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1048 wantRWHandle fun handle act =
1049 withHandle_ handle $ \ handle_ -> do
1050 case haType__ handle_ of
1051 ClosedHandle -> ioe_closedHandle fun handle
1052 SemiClosedHandle -> ioe_closedHandle fun handle
1055 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1056 wantSeekableHandle fun handle act =
1057 withHandle_ handle $ \ handle_ -> do
1058 case haType__ handle_ of
1059 ClosedHandle -> ioe_closedHandle fun handle
1060 SemiClosedHandle -> ioe_closedHandle fun handle
1064 Internal function for creating an @IOError@ representing the
1065 access to a closed file.
1068 ioe_closedHandle :: String -> Handle -> IO a
1069 ioe_closedHandle fun h = ioError (IOException (IOError (Just h) IllegalOperation fun
1070 "handle is closed"))
1073 Internal helper functions for Concurrent Haskell implementation
1077 mayBlock :: FILE_OBJECT -> IO Int -> IO Int
1078 mayBlock fo act = do
1081 -5 -> do -- (possibly blocking) read
1084 mayBlock fo act -- input available, re-try
1085 -6 -> do -- (possibly blocking) write
1088 mayBlock fo act -- output possible
1089 -7 -> do -- (possibly blocking) write on connected handle
1090 fd <- getConnFileFd fo
1092 mayBlock fo act -- output possible
1101 mayBlockRead :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1102 mayBlockRead fname handle fn = do
1103 r <- wantReadableHandle fname handle $ \ handle_ -> do
1104 let fo = haFO__ handle_
1107 -5 -> do -- (possibly blocking) read
1109 return (BlockRead fd)
1110 -6 -> do -- (possibly blocking) write
1112 return (BlockWrite fd)
1113 -7 -> do -- (possibly blocking) write on connected handle
1114 fd <- getConnFileFd fo
1115 return (BlockWrite fd)
1118 then return (NoBlock rc)
1119 else constructErrorAndFail fname
1123 mayBlockRead fname handle fn
1126 mayBlockRead fname handle fn
1127 NoBlock c -> return c
1129 mayBlockRead' :: String -> Handle
1130 -> (FILE_OBJECT -> IO Int)
1131 -> (FILE_OBJECT -> Int -> IO a)
1133 mayBlockRead' fname handle fn io = do
1134 r <- wantReadableHandle fname handle $ \ handle_ -> do
1135 let fo = haFO__ handle_
1138 -5 -> do -- (possibly blocking) read
1140 return (BlockRead fd)
1141 -6 -> do -- (possibly blocking) write
1143 return (BlockWrite fd)
1144 -7 -> do -- (possibly blocking) write on connected handle
1145 fd <- getConnFileFd fo
1146 return (BlockWrite fd)
1149 then do a <- io fo rc
1151 else constructErrorAndFail fname
1155 mayBlockRead' fname handle fn io
1158 mayBlockRead' fname handle fn io
1159 NoBlock c -> return c
1161 mayBlockWrite :: String -> Handle -> (FILE_OBJECT -> IO Int) -> IO Int
1162 mayBlockWrite fname handle fn = do
1163 r <- wantWriteableHandle fname handle $ \ handle_ -> do
1164 let fo = haFO__ handle_
1167 -5 -> do -- (possibly blocking) read
1169 return (BlockRead fd)
1170 -6 -> do -- (possibly blocking) write
1172 return (BlockWrite fd)
1173 -7 -> do -- (possibly blocking) write on connected handle
1174 fd <- getConnFileFd fo
1175 return (BlockWrite fd)
1178 then return (NoBlock rc)
1179 else constructErrorAndFail fname
1183 mayBlockWrite fname handle fn
1186 mayBlockWrite fname handle fn
1187 NoBlock c -> return c
1190 Foreign import declarations of helper functions:
1195 type Bytes = PrimByteArray RealWorld
1197 type Bytes = ByteArray#
1200 foreign import "libHS_cbits" "inputReady" unsafe
1201 inputReady :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1202 foreign import "libHS_cbits" "fileGetc" unsafe
1203 fileGetc :: FILE_OBJECT -> IO Int
1204 foreign import "libHS_cbits" "fileLookAhead" unsafe
1205 fileLookAhead :: FILE_OBJECT -> IO Int
1206 foreign import "libHS_cbits" "readBlock" unsafe
1207 readBlock :: FILE_OBJECT -> IO Int
1208 foreign import "libHS_cbits" "readLine" unsafe
1209 readLine :: FILE_OBJECT -> IO Int
1210 foreign import "libHS_cbits" "readChar" unsafe
1211 readChar :: FILE_OBJECT -> IO Int
1212 foreign import "libHS_cbits" "writeFileObject" unsafe
1213 writeFileObject :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1214 foreign import "libHS_cbits" "filePutc" unsafe
1215 filePutc :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1216 foreign import "libHS_cbits" "write_" unsafe
1217 write_ :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1218 foreign import "libHS_cbits" "getBufStart" unsafe
1219 getBufStart :: FILE_OBJECT -> Int -> IO Addr
1220 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1221 getWriteableBuf :: FILE_OBJECT -> IO Addr
1222 foreign import "libHS_cbits" "getBuf" unsafe
1223 getBuf :: FILE_OBJECT -> IO Addr
1224 foreign import "libHS_cbits" "getBufWPtr" unsafe
1225 getBufWPtr :: FILE_OBJECT -> IO Int
1226 foreign import "libHS_cbits" "setBufWPtr" unsafe
1227 setBufWPtr :: FILE_OBJECT -> Int -> IO ()
1228 foreign import "libHS_cbits" "closeFile" unsafe
1229 closeFile :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1230 foreign import "libHS_cbits" "fileEOF" unsafe
1231 fileEOF :: FILE_OBJECT -> IO Int{-ret code-}
1232 foreign import "libHS_cbits" "setBuffering" unsafe
1233 setBuffering :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1234 foreign import "libHS_cbits" "flushFile" unsafe
1235 flushFile :: FILE_OBJECT -> IO Int{-ret code-}
1236 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1237 flushConnectedBuf :: FILE_OBJECT -> IO ()
1238 foreign import "libHS_cbits" "getBufferMode" unsafe
1239 getBufferMode :: FILE_OBJECT -> IO Int{-ret code-}
1241 foreign import "libHS_cbits" "seekFile_int64" unsafe
1242 seekFile :: FILE_OBJECT -> Int -> Int64 -> IO Int
1244 foreign import "libHS_cbits" "seekFile" unsafe
1245 seekFile :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1248 foreign import "libHS_cbits" "seekFileP" unsafe
1249 seekFileP :: FILE_OBJECT -> IO Int{-ret code-}
1250 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1251 setTerminalEcho :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1252 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1253 getTerminalEcho :: FILE_OBJECT -> IO Int{-ret code-}
1254 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1255 isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1256 foreign import "libHS_cbits" "setConnectedTo" unsafe
1257 setConnectedTo :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1258 foreign import "libHS_cbits" "ungetChar" unsafe
1259 ungetChar :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1260 foreign import "libHS_cbits" "readChunk" unsafe
1261 readChunk :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1262 foreign import "libHS_cbits" "getFileFd" unsafe
1263 getFileFd :: FILE_OBJECT -> IO Int{-fd-}
1265 foreign import "libHS_cbits" "fileSize_int64" unsafe
1266 fileSize_int64 :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1268 foreign import "libHS_cbits" "fileSize" unsafe
1269 fileSize :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1272 foreign import "libHS_cbits" "getFilePosn" unsafe
1273 getFilePosn :: FILE_OBJECT -> IO Int
1274 foreign import "libHS_cbits" "setFilePosn" unsafe
1275 setFilePosn :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1276 foreign import "libHS_cbits" "getConnFileFd" unsafe
1277 getConnFileFd :: FILE_OBJECT -> IO Int{-fd-}
1278 foreign import "libHS_cbits" "getLock" unsafe
1279 getLock :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1280 foreign import "libHS_cbits" "openStdFile" unsafe
1281 openStdFile :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1282 foreign import "libHS_cbits" "openFile" unsafe
1283 primOpenFile :: ByteArray Int{-CString-}
1286 -> IO Addr {-file obj-}
1287 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1290 foreign import "libHS_cbits" "setBinaryMode__" unsafe
1291 setBinaryMode :: FILE_OBJECT -> Int -> IO Int