2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[PrelHandle]{Module @PrelHandle@}
7 This module defines Haskell {\em handles} and the basic operations
8 which are supported for them.
11 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
12 #include "cbits/stgerror.h"
14 #ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
15 module PrelHandle where
18 import PrelAddr ( Addr, nullAddr )
19 import PrelArr ( newVar, readVar, writeVar )
20 import PrelByteArr ( ByteArray(..) )
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 )
37 #ifdef __CONCURRENT_HASKELL__
41 #ifndef __PARALLEL_HASKELL__
42 import PrelForeign ( makeForeignObj )
45 #endif /* ndef(__HUGS__) */
48 #define __CONCURRENT_HASKELL__
52 #ifndef __PARALLEL_HASKELL__
53 #define FILE_OBJECT ForeignObj
55 #define FILE_OBJECT Addr
59 %*********************************************************
61 \subsection{Types @Handle@, @Handle__@}
63 %*********************************************************
65 The @Handle@ and @Handle__@ types are defined in @IOBase@.
68 {-# INLINE newHandle #-}
69 {-# INLINE withHandle #-}
70 newHandle :: Handle__ -> IO Handle
72 #if defined(__CONCURRENT_HASKELL__)
74 -- Use MVars for concurrent Haskell
75 newHandle hc = newMVar hc >>= \ h ->
79 -- Use ordinary MutableVars for non-concurrent Haskell
80 newHandle hc = stToIO (newVar hc >>= \ h ->
85 %*********************************************************
87 \subsection{@withHandle@ operations}
89 %*********************************************************
91 In the concurrent world, handles are locked during use. This is done
92 by wrapping an MVar around the handle which acts as a mutex over
93 operations on the handle.
95 To avoid races, we use the following bracketing operations. The idea
96 is to obtain the lock, do some operation and replace the lock again,
97 whether the operation succeeded or failed. We also want to handle the
98 case where the thread receives an exception while processing the IO
99 operation: in these cases we also want to relinquish the lock.
101 There are three versions of @withHandle@: corresponding to the three
102 possible combinations of:
104 - the operation may side-effect the handle
105 - the operation may return a result
107 If the operation generates an error or an exception is raised, the
108 orignal handle is always replaced [ this is the case at the moment,
109 but we might want to revisit this in the future --SDM ].
112 #ifdef __CONCURRENT_HASKELL__
113 withHandle :: Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
114 withHandle (Handle h) act = do
116 (h',v) <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
120 withHandle_ :: Handle -> (Handle__ -> IO a) -> IO a
121 withHandle_ (Handle h) act = do
123 v <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
127 withHandle__ :: Handle -> (Handle__ -> IO Handle__) -> IO ()
128 withHandle__ (Handle h) act = do
130 h' <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
135 -- of questionable value to install this exception
136 -- handler, but let's do it in the non-concurrent
137 -- case too, for now.
138 withHandle (Handle h) act = do
139 h_ <- stToIO (readVar h)
140 v <- catchException (act h_) (\ ex -> stToIO (writeVar h h_) >> throw ex)
146 nullFile__ is only used for closed handles, plugging it in as a null
147 file object reference.
150 nullFile__ :: FILE_OBJECT
152 #ifndef __PARALLEL_HASKELL__
153 unsafePerformIO (makeForeignObj nullAddr)
159 mkClosedHandle__ :: Handle__
167 mkErrorHandle__ :: IOError -> Handle__
168 mkErrorHandle__ ioe =
176 %*********************************************************
178 \subsection{Handle Finalizers}
180 %*********************************************************
183 foreign import "libHS_cbits" "freeStdFileObject" unsafe
184 freeStdFileObject :: FILE_OBJECT -> IO ()
185 foreign import "libHS_cbits" "freeFileObject" unsafe
186 freeFileObject :: FILE_OBJECT -> IO ()
190 %*********************************************************
192 \subsection[StdHandles]{Standard handles}
194 %*********************************************************
196 Three handles are allocated during program initialisation. The first
197 two manage input or output from the Haskell program's standard input
198 or output channel respectively. The third manages output to the
199 standard error channel. These handles are initially open.
203 stdin, stdout, stderr :: Handle
205 stdout = unsafePerformIO (do
206 rc <- getLock (1::Int) (1::Int) -- ConcHask: SAFE, won't block
208 0 -> newHandle (mkClosedHandle__)
210 fo <- openStdFile (1::Int)
211 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
213 #ifndef __PARALLEL_HASKELL__
214 fo <- makeForeignObj fo
215 addForeignFinalizer fo (freeStdFileObject fo)
219 /* I dont care what the Haskell report says, in an interactive system,
220 * stdout should be unbuffered by default.
224 (bm, bf_size) <- getBMode__ fo
225 mkBuffer__ fo bf_size
227 newHandle (Handle__ fo WriteHandle bm "stdout")
228 _ -> do ioError <- constructError "stdout"
229 newHandle (mkErrorHandle__ ioError)
232 stdin = unsafePerformIO (do
233 rc <- getLock (0::Int) (0::Int) -- ConcHask: SAFE, won't block
235 0 -> newHandle (mkClosedHandle__)
237 fo <- openStdFile (0::Int)
238 (1::Int){-readable-} -- ConcHask: SAFE, won't block
240 #ifndef __PARALLEL_HASKELL__
241 fo <- makeForeignObj fo
242 addForeignFinalizer fo (freeStdFileObject fo)
244 (bm, bf_size) <- getBMode__ fo
245 mkBuffer__ fo bf_size
246 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin")
247 -- when stdin and stdout are both connected to a terminal, ensure
248 -- that anything buffered on stdout is flushed prior to reading from stdin.
250 hConnectTerms stdout hdl
252 _ -> do ioError <- constructError "stdin"
253 newHandle (mkErrorHandle__ ioError)
257 stderr = unsafePerformIO (do
258 rc <- getLock (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
260 0 -> newHandle (mkClosedHandle__)
262 fo <- openStdFile (2::Int)
263 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
265 #ifndef __PARALLEL_HASKELL__
266 fo <- makeForeignObj fo
267 addForeignFinalizer fo (freeStdFileObject fo)
269 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr")
270 -- when stderr and stdout are both connected to a terminal, ensure
271 -- that anything buffered on stdout is flushed prior to writing to
273 hConnectTo stdout hdl
276 _ -> do ioError <- constructError "stderr"
277 newHandle (mkErrorHandle__ ioError)
281 %*********************************************************
283 \subsection[OpeningClosing]{Opening and Closing Files}
285 %*********************************************************
288 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
289 deriving (Eq, Ord, Ix, Enum, Read, Show)
294 deriving (Eq, Read, Show)
296 openFile :: FilePath -> IOMode -> IO Handle
297 openFile fp im = openFileEx fp (TextMode im)
299 openFileEx :: FilePath -> IOModeEx -> IO Handle
302 fo <- primOpenFile (packString f)
304 (binary::Int) -- ConcHask: SAFE, won't block
305 if fo /= nullAddr then do
306 #ifndef __PARALLEL_HASKELL__
307 fo <- makeForeignObj fo
308 addForeignFinalizer fo (freeFileObject fo)
310 (bm, bf_size) <- getBMode__ fo
311 mkBuffer__ fo bf_size
312 newHandle (Handle__ fo htype bm f)
314 constructErrorAndFailWithInfo "openFile" f
318 BinaryMode bmo -> (bmo, 1)
319 TextMode tmo -> (tmo, 0)
329 ReadMode -> ReadHandle
330 WriteMode -> WriteHandle
331 AppendMode -> AppendHandle
332 ReadWriteMode -> ReadWriteHandle
335 Computation $openFile file mode$ allocates and returns a new, open
336 handle to manage the file {\em file}. It manages input if {\em mode}
337 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
338 and both input and output if mode is $ReadWriteMode$.
340 If the file does not exist and it is opened for output, it should be
341 created as a new file. If {\em mode} is $WriteMode$ and the file
342 already exists, then it should be truncated to zero length. The
343 handle is positioned at the end of the file if {\em mode} is
344 $AppendMode$, and otherwise at the beginning (in which case its
345 internal position is 0).
347 Implementations should enforce, locally to the Haskell process,
348 multiple-reader single-writer locking on files, which is to say that
349 there may either be many handles on the same file which manage input,
350 or just one handle on the file which manages output. If any open or
351 semi-closed handle is managing a file for output, no new handle can be
352 allocated for that file. If any open or semi-closed handle is
353 managing a file for input, new handles can only be allocated if they
354 do not manage output.
356 Two files are the same if they have the same absolute name. An
357 implementation is free to impose stricter conditions.
360 hClose :: Handle -> IO ()
363 withHandle__ handle $ \ handle_ -> do
364 case haType__ handle_ of
365 ErrorHandle theError -> ioError theError
366 ClosedHandle -> return handle_
368 rc <- closeFile (haFO__ handle_)
369 (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
370 {- We explicitly close a file object so that we can be told
371 if there were any errors. Note that after @hClose@
372 has been performed, the ForeignObj embedded in the Handle
373 is still lying around in the heap, so care is taken
374 to avoid closing the file object when the ForeignObj
375 is finalized. (we overwrite the file ptr in the underlying
376 FileObject with a NULL as part of closeFile())
379 then return (handle_{ haType__ = ClosedHandle,
380 haFO__ = nullFile__ })
381 else constructErrorAndFail "hClose"
385 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
386 computation finishes, any items buffered for output and not already
387 sent to the operating system are flushed as for $flush$.
389 %*********************************************************
391 \subsection[EOF]{Detecting the End of Input}
393 %*********************************************************
396 For a handle {\em hdl} which attached to a physical file, $hFileSize
397 hdl$ returns the size of {\em hdl} in terms of the number of items
398 which can be read from {\em hdl}.
401 hFileSize :: Handle -> IO Integer
403 withHandle_ handle $ \ handle_ -> do
404 case haType__ handle_ of
405 ErrorHandle theError -> ioError theError
406 ClosedHandle -> ioe_closedHandle "hFileSize" handle
407 SemiClosedHandle -> ioe_closedHandle "hFileSize" handle
410 mem <- primNewByteArray 8{-sizeof_int64-}
411 rc <- fileSize_int64 (haFO__ handle_) mem -- ConcHask: SAFE, won't block
413 result <- primReadInt64Array mem 0
414 return (primInt64ToInteger result)
416 constructErrorAndFail "hFileSize"
419 -- HACK! We build a unique MP_INT of the right shape to hold
420 -- a single unsigned word, and we let the C routine
421 -- change the data bits
423 case int2Integer# 1# of
425 rc <- fileSize (haFO__ handle_) d -- ConcHask: SAFE, won't block
426 if rc == (0::Int) then
429 constructErrorAndFail "hFileSize"
433 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
434 @True@ if no further input can be taken from @hdl@ or for a
435 physical file, if the current I/O position is equal to the length of
436 the file. Otherwise, it returns @False@.
439 hIsEOF :: Handle -> IO Bool
441 wantReadableHandle "hIsEOF" handle $ \ handle_ -> do
442 let fo = haFO__ handle_
443 rc <- mayBlock fo (fileEOF fo) -- ConcHask: UNSAFE, may block
447 _ -> constructErrorAndFail "hIsEOF"
453 %*********************************************************
455 \subsection[Buffering]{Buffering Operations}
457 %*********************************************************
459 Three kinds of buffering are supported: line-buffering,
460 block-buffering or no-buffering. See @IOBase@ for definition
461 and further explanation of what the type represent.
463 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
464 handle {\em hdl} on subsequent reads and writes.
468 If {\em mode} is @LineBuffering@, line-buffering should be
471 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
472 should be enabled if possible. The size of the buffer is {\em n} items
473 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
475 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
478 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
479 to @NoBuffering@, then any items in the output buffer are written to
480 the device, and any items in the input buffer are discarded. The
481 default buffering mode when a handle is opened is
482 implementation-dependent and may depend on the object which is
483 attached to that handle.
486 hSetBuffering :: Handle -> BufferMode -> IO ()
488 hSetBuffering handle mode =
490 BlockBuffering (Just n)
492 (IOError (Just handle)
495 ("illegal buffer size " ++ showsPrec 9 n [])) -- 9 => should be parens'ified.
497 withHandle__ handle $ \ handle_ -> do
498 case haType__ handle_ of
499 ErrorHandle theError -> ioError theError
500 ClosedHandle -> ioe_closedHandle "hSetBuffering" handle
503 - we flush the old buffer regardless of whether
504 the new buffer could fit the contents of the old buffer
506 - allow a handle's buffering to change even if IO has
507 occurred (ANSI C spec. does not allow this, nor did
508 the previous implementation of IO.hSetBuffering).
509 - a non-standard extension is to allow the buffering
510 of semi-closed handles to change [sof 6/98]
512 let fo = haFO__ handle_
513 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
516 return (handle_{ haBufferMode__ = mode })
518 -- Note: failure to change the buffer size will cause old buffer to be flushed.
519 constructErrorAndFail "hSetBuffering"
525 BlockBuffering Nothing -> -2
526 BlockBuffering (Just n) -> n
529 The action @hFlush hdl@ causes any items buffered for output
530 in handle {\em hdl} to be sent immediately to the operating
534 hFlush :: Handle -> IO ()
536 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
537 let fo = haFO__ handle_
538 rc <- mayBlock fo (flushFile fo) -- ConcHask: UNSAFE, may block
542 constructErrorAndFail "hFlush"
547 %*********************************************************
549 \subsection[Seeking]{Repositioning Handles}
551 %*********************************************************
556 Handle -- Q: should this be a weak or strong ref. to the handle?
557 -- [what's the winning argument for it not being strong? --sof]
560 instance Eq HandlePosn where
561 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
563 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
564 -- We represent it as an Integer on the Haskell side, but
565 -- cheat slightly in that hGetPosn calls upon a C helper
566 -- that reports the position back via (merely) an Int.
567 type HandlePosition = Integer
569 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
570 mkHandlePosn h p = HandlePosn h p
572 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
573 deriving (Eq, Ord, Ix, Enum, Read, Show)
576 Computation @hGetPosn hdl@ returns the current I/O
577 position of {\em hdl} as an abstract position. Computation
578 $hSetPosn p$ sets the position of {\em hdl}
579 to a previously obtained position {\em p}.
582 hGetPosn :: Handle -> IO HandlePosn
584 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
585 posn <- getFilePosn (haFO__ handle_) -- ConcHask: SAFE, won't block
586 if posn /= -1 then do
587 return (mkHandlePosn handle (fromInt posn))
589 constructErrorAndFail "hGetPosn"
591 hSetPosn :: HandlePosn -> IO ()
592 hSetPosn (HandlePosn handle i@(S# _)) = hSetPosn (HandlePosn handle (toBig i))
593 hSetPosn (HandlePosn handle (J# s# d#)) =
594 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do
595 -- not as silly as it looks: the handle may have been closed in the meantime.
596 let fo = haFO__ handle_
597 rc <- mayBlock fo (setFilePosn fo (I# s#) d#) -- ConcHask: UNSAFE, may block
601 constructErrorAndFail "hSetPosn"
604 The action @hSeek hdl mode i@ sets the position of handle
605 @hdl@ depending on @mode@. If @mode@ is
607 * AbsoluteSeek - The position of @hdl@ is set to @i@.
608 * RelativeSeek - The position of @hdl@ is set to offset @i@ from
609 the current position.
610 * SeekFromEnd - The position of @hdl@ is set to offset @i@ from
613 Some handles may not be seekable (see @hIsSeekable@), or only
614 support a subset of the possible positioning operations (e.g. it may
615 only be possible to seek to the end of a tape, or to a positive
616 offset from the beginning or current position).
618 It is not possible to set a negative I/O position, or for a physical
619 file, an I/O position beyond the current end-of-file.
622 - when seeking using @SeekFromEnd@, positive offsets (>=0) means
623 seeking at or past EOF.
624 - relative seeking on buffered handles can lead to non-obvious results.
627 hSeek :: Handle -> SeekMode -> Integer -> IO ()
629 hSeek handle mode offset =
630 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
631 let fo = haFO__ handle_
632 rc <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
634 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
635 hSeek handle mode (J# s# d#) =
636 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
637 let fo = haFO__ handle_
638 rc <- mayBlock fo (seekFile fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
643 constructErrorAndFail "hSeek"
646 whence = case mode of
652 %*********************************************************
654 \subsection[Query]{Handle Properties}
656 %*********************************************************
658 A number of operations return information about the properties of a
659 handle. Each of these operations returns $True$ if the
660 handle has the specified property, and $False$
663 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
664 {\em hdl} is not block-buffered. Otherwise it returns
665 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
666 $( Just n )$ for block-buffering of {\em n} bytes.
669 hIsOpen :: Handle -> IO Bool
671 withHandle_ handle $ \ handle_ -> do
672 case haType__ handle_ of
673 ErrorHandle theError -> ioError theError
674 ClosedHandle -> return False
675 SemiClosedHandle -> return False
678 hIsClosed :: Handle -> IO Bool
680 withHandle_ handle $ \ handle_ -> do
681 case haType__ handle_ of
682 ErrorHandle theError -> ioError theError
683 ClosedHandle -> return True
686 {- not defined, nor exported, but mentioned
687 here for documentation purposes:
689 hSemiClosed :: Handle -> IO Bool
693 return (not (ho || hc))
696 hIsReadable :: Handle -> IO Bool
698 withHandle_ handle $ \ handle_ -> do
699 case haType__ handle_ of
700 ErrorHandle theError -> ioError theError
701 ClosedHandle -> ioe_closedHandle "hIsReadable" handle
702 SemiClosedHandle -> ioe_closedHandle "hIsReadable" handle
703 htype -> return (isReadable htype)
705 isReadable ReadHandle = True
706 isReadable ReadWriteHandle = True
709 hIsWritable :: Handle -> IO Bool
711 withHandle_ handle $ \ handle_ -> do
712 case haType__ handle_ of
713 ErrorHandle theError -> ioError theError
714 ClosedHandle -> ioe_closedHandle "hIsWritable" handle
715 SemiClosedHandle -> ioe_closedHandle "hIsWritable" handle
716 htype -> return (isWritable htype)
718 isWritable AppendHandle = True
719 isWritable WriteHandle = True
720 isWritable ReadWriteHandle = True
724 #ifndef __PARALLEL_HASKELL__
725 getBMode__ :: ForeignObj -> IO (BufferMode, Int)
727 getBMode__ :: Addr -> IO (BufferMode, Int)
730 rc <- getBufferMode fo -- ConcHask: SAFE, won't block
732 0 -> return (NoBuffering, 0)
733 -1 -> return (LineBuffering, default_buffer_size)
734 -2 -> return (BlockBuffering Nothing, default_buffer_size)
735 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
736 n -> return (BlockBuffering (Just n), n)
738 default_buffer_size :: Int
739 default_buffer_size = (const_BUFSIZ - 1)
742 Querying how a handle buffers its data:
745 hGetBuffering :: Handle -> IO BufferMode
746 hGetBuffering handle =
747 withHandle_ handle $ \ handle_ -> do
748 case haType__ handle_ of
749 ErrorHandle theError -> ioError theError
750 ClosedHandle -> ioe_closedHandle "hGetBuffering" handle
753 We're being non-standard here, and allow the buffering
754 of a semi-closed handle to be queried. -- sof 6/98
756 return (haBufferMode__ handle_) -- could be stricter..
760 hIsSeekable :: Handle -> IO Bool
762 withHandle_ handle $ \ handle_ -> do
763 case haType__ handle_ of
764 ErrorHandle theError -> ioError theError
765 ClosedHandle -> ioe_closedHandle "hIsSeekable" handle
766 SemiClosedHandle -> ioe_closedHandle "hIsSeekable" handle
767 AppendHandle -> return False
769 rc <- seekFileP (haFO__ handle_) -- ConcHask: SAFE, won't block
773 _ -> constructErrorAndFail "hIsSeekable"
777 %*********************************************************
779 \subsection{Changing echo status}
781 %*********************************************************
783 Non-standard GHC extension is to allow the echoing status
784 of a handles connected to terminals to be reconfigured:
787 hSetEcho :: Handle -> Bool -> IO ()
788 hSetEcho handle on = do
789 isT <- hIsTerminalDevice handle
793 withHandle_ handle $ \ handle_ -> do
794 case haType__ handle_ of
795 ErrorHandle theError -> ioError theError
796 ClosedHandle -> ioe_closedHandle "hSetEcho" handle
798 rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0) -- ConcHask: SAFE, won't block
801 else constructErrorAndFail "hSetEcho"
803 hGetEcho :: Handle -> IO Bool
805 isT <- hIsTerminalDevice handle
809 withHandle_ handle $ \ handle_ -> do
810 case haType__ handle_ of
811 ErrorHandle theError -> ioError theError
812 ClosedHandle -> ioe_closedHandle "hGetEcho" handle
814 rc <- getTerminalEcho (haFO__ handle_) -- ConcHask: SAFE, won't block
818 _ -> constructErrorAndFail "hSetEcho"
820 hIsTerminalDevice :: Handle -> IO Bool
821 hIsTerminalDevice handle = do
822 withHandle_ handle $ \ handle_ -> do
823 case haType__ handle_ of
824 ErrorHandle theError -> ioError theError
825 ClosedHandle -> ioe_closedHandle "hIsTerminalDevice" handle
827 rc <- isTerminalDevice (haFO__ handle_) -- ConcHask: SAFE, won't block
831 _ -> constructErrorAndFail "hIsTerminalDevice"
835 hConnectTerms :: Handle -> Handle -> IO ()
836 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
838 hConnectTo :: Handle -> Handle -> IO ()
839 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
841 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
842 hConnectHdl_ hW hR is_tty =
843 wantRWHandle "hConnectTo" hW $ \ hW_ ->
844 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
845 setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
847 #ifndef __PARALLEL_HASKELL__
848 #define FILE_OBJECT ForeignObj
850 #define FILE_OBJECT Addr
855 As an extension, we also allow characters to be pushed back.
856 Like ANSI C stdio, we guarantee no more than one character of
857 pushback. (For unbuffered channels, the (default) push-back limit is
861 hUngetChar :: Handle -> Char -> IO ()
862 hUngetChar handle c =
863 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
864 rc <- ungetChar (haFO__ handle_) c -- ConcHask: SAFE, won't block
866 then constructErrorAndFail "hUngetChar"
872 Hoisting files in in one go is sometimes useful, so we support
873 this as an extension:
876 -- in one go, read file into an externally allocated buffer.
877 slurpFile :: FilePath -> IO (Addr, Int)
879 handle <- openFile fname ReadMode
880 sz <- hFileSize handle
881 if sz > toInteger (maxBound::Int) then
882 ioError (userError "slurpFile: file too big")
884 let sz_i = fromInteger sz
885 chunk <- allocMemory__ sz_i
889 constructErrorAndFail "slurpFile"
891 rc <- withHandle_ handle ( \ handle_ -> do
892 let fo = haFO__ handle_
893 mayBlock fo (readChunk fo chunk sz_i) -- ConcHask: UNSAFE, may block.
897 then constructErrorAndFail "slurpFile"
898 else return (chunk, rc)
900 #ifndef __HUGS__ /* Hugs' Prelude doesn't need this */
901 hFillBufBA :: Handle -> ByteArray Int -> Int -> IO Int
902 hFillBufBA handle buf sz
903 | sz <= 0 = ioError (IOError (Just handle)
906 ("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
908 wantReadableHandle "hFillBufBA" handle $ \ handle_ -> do
909 let fo = haFO__ handle_
910 rc <- mayBlock fo (readChunkBA fo buf sz) -- ConcHask: UNSAFE, may block.
913 else constructErrorAndFail "hFillBufBA"
916 hFillBuf :: Handle -> Addr -> Int -> IO Int
917 hFillBuf handle buf sz
918 | sz <= 0 = ioError (IOError (Just handle)
921 ("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
923 wantReadableHandle "hFillBuf" handle $ \ handle_ -> do
924 let fo = haFO__ handle_
925 rc <- mayBlock fo (readChunk fo buf sz) -- ConcHask: UNSAFE, may block.
928 else constructErrorAndFail "hFillBuf"
932 The @hPutBuf hdl buf len@ action writes an already packed sequence of
933 bytes to the file/channel managed by @hdl@ - non-standard.
936 hPutBuf :: Handle -> Addr -> Int -> IO ()
937 hPutBuf handle buf len =
938 wantWriteableHandle "hPutBuf" handle $ \ handle_ -> do
939 let fo = haFO__ handle_
940 rc <- mayBlock fo (writeBuf fo buf len) -- ConcHask: UNSAFE, may block.
943 else constructErrorAndFail "hPutBuf"
945 #ifndef __HUGS__ /* An_ one Hugs doesn't provide */
946 hPutBufBA :: Handle -> ByteArray Int -> Int -> IO ()
947 hPutBufBA handle buf len =
948 wantWriteableHandle "hPutBufBA" handle $ \ handle_ -> do
949 let fo = haFO__ handle_
950 rc <- mayBlock fo (writeBufBA fo buf len) -- ConcHask: UNSAFE, may block.
953 else constructErrorAndFail "hPutBuf"
957 Sometimes it's useful to get at the file descriptor that
958 the Handle contains..
961 getHandleFd :: Handle -> IO Int
963 withHandle_ handle $ \ handle_ -> do
964 case (haType__ handle_) of
965 ErrorHandle theError -> ioError theError
966 ClosedHandle -> ioe_closedHandle "getHandleFd" handle
968 fd <- getFileFd (haFO__ handle_)
973 %*********************************************************
975 \subsection{Miscellaneous}
977 %*********************************************************
979 These three functions are meant to get things out of @IOErrors@.
984 ioeGetFileName :: IOError -> Maybe FilePath
985 ioeGetErrorString :: IOError -> String
986 ioeGetHandle :: IOError -> Maybe Handle
988 ioeGetHandle (IOError h _ _ _) = h
989 ioeGetErrorString (IOError _ iot _ str) =
994 ioeGetFileName (IOError _ _ _ str) =
995 case span (/=':') str of
1001 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
1002 PrelMain.mainIO) and report them - topHandler is the exception
1003 handler they should use for this:
1006 -- make sure we handle errors while reporting the error!
1007 -- (e.g. evaluating the string passed to 'error' might generate
1008 -- another error, etc.)
1009 topHandler :: Bool -> Exception -> IO ()
1010 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
1012 real_handler :: Bool -> Exception -> IO ()
1013 real_handler bombOut ex =
1015 AsyncException StackOverflow -> reportStackOverflow bombOut
1016 ErrorCall s -> reportError bombOut s
1017 other -> reportError bombOut (showsPrec 0 other "\n")
1019 reportStackOverflow :: Bool -> IO ()
1020 reportStackOverflow bombOut = do
1021 (hFlush stdout) `catchException` (\ _ -> return ())
1022 callStackOverflowHook
1028 reportError :: Bool -> String -> IO ()
1029 reportError bombOut str = do
1030 (hFlush stdout) `catchException` (\ _ -> return ())
1031 let bs@(ByteArray _ len _) = packString str
1032 writeErrString addrOf_ErrorHdrHook bs len
1038 foreign label "ErrorHdrHook"
1039 addrOf_ErrorHdrHook :: Addr
1041 foreign import ccall "writeErrString__" unsafe
1042 writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1044 foreign import ccall "stackOverflow"
1045 callStackOverflowHook :: IO ()
1047 foreign import ccall "stg_exit"
1048 stg_exit :: Int -> IO ()
1052 A number of operations want to get at a readable or writeable handle, and fail
1056 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1057 wantReadableHandle fun handle act =
1058 withHandle_ handle $ \ handle_ -> do
1059 case haType__ handle_ of
1060 ErrorHandle theError -> ioError theError
1061 ClosedHandle -> ioe_closedHandle fun handle
1062 SemiClosedHandle -> ioe_closedHandle fun handle
1063 AppendHandle -> ioError not_readable_error
1064 WriteHandle -> ioError not_readable_error
1067 not_readable_error =
1068 IOError (Just handle) IllegalOperation fun
1069 ("handle is not open for reading")
1071 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1072 wantWriteableHandle fun handle act =
1073 withHandle_ handle $ \ handle_ -> do
1074 case haType__ handle_ of
1075 ErrorHandle theError -> ioError theError
1076 ClosedHandle -> ioe_closedHandle fun handle
1077 SemiClosedHandle -> ioe_closedHandle fun handle
1078 ReadHandle -> ioError not_writeable_error
1081 not_writeable_error =
1082 IOError (Just handle) IllegalOperation fun
1083 ("handle is not open for writing")
1085 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1086 wantRWHandle fun handle act =
1087 withHandle_ handle $ \ handle_ -> do
1088 case haType__ handle_ of
1089 ErrorHandle theError -> ioError theError
1090 ClosedHandle -> ioe_closedHandle fun handle
1091 SemiClosedHandle -> ioe_closedHandle fun handle
1094 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1095 wantSeekableHandle fun handle act =
1096 withHandle_ handle $ \ handle_ -> do
1097 case haType__ handle_ of
1098 ErrorHandle theError -> ioError theError
1099 ClosedHandle -> ioe_closedHandle fun handle
1100 SemiClosedHandle -> ioe_closedHandle fun handle
1103 not_seekable_error =
1104 IOError (Just handle)
1105 IllegalOperation fun
1106 ("handle is not seekable")
1110 Internal function for creating an @IOError@ representing the
1111 access to a closed file.
1114 ioe_closedHandle :: String -> Handle -> IO a
1115 ioe_closedHandle fun h = ioError (IOError (Just h) IllegalOperation fun "handle is closed")
1118 Internal helper functions for Concurrent Haskell implementation
1122 #ifndef __PARALLEL_HASKELL__
1123 mayBlock :: ForeignObj -> IO Int -> IO Int
1125 mayBlock :: Addr -> IO Int -> IO Int
1128 mayBlock fo act = do
1131 -5 -> do -- (possibly blocking) read
1134 mayBlock fo act -- input available, re-try
1135 -6 -> do -- (possibly blocking) write
1138 mayBlock fo act -- output possible
1139 -7 -> do -- (possibly blocking) write on connected handle
1140 fd <- getConnFileFd fo
1142 mayBlock fo act -- output possible
1147 Foreign import declarations of helper functions:
1152 type Bytes = PrimByteArray RealWorld
1154 type Bytes = ByteArray#
1157 foreign import "libHS_cbits" "inputReady" unsafe
1158 inputReady :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1159 foreign import "libHS_cbits" "fileGetc" unsafe
1160 fileGetc :: FILE_OBJECT -> IO Int
1161 foreign import "libHS_cbits" "fileLookAhead" unsafe
1162 fileLookAhead :: FILE_OBJECT -> IO Int
1163 foreign import "libHS_cbits" "readBlock" unsafe
1164 readBlock :: FILE_OBJECT -> IO Int
1165 foreign import "libHS_cbits" "readLine" unsafe
1166 readLine :: FILE_OBJECT -> IO Int
1167 foreign import "libHS_cbits" "readChar" unsafe
1168 readChar :: FILE_OBJECT -> IO Int
1169 foreign import "libHS_cbits" "writeFileObject" unsafe
1170 writeFileObject :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1171 foreign import "libHS_cbits" "filePutc" unsafe
1172 filePutc :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1173 foreign import "libHS_cbits" "getBufStart" unsafe
1174 getBufStart :: FILE_OBJECT -> Int -> IO Addr
1175 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1176 getWriteableBuf :: FILE_OBJECT -> IO Addr
1177 foreign import "libHS_cbits" "getBufWPtr" unsafe
1178 getBufWPtr :: FILE_OBJECT -> IO Int
1179 foreign import "libHS_cbits" "setBufWPtr" unsafe
1180 setBufWPtr :: FILE_OBJECT -> Int -> IO ()
1181 foreign import "libHS_cbits" "closeFile" unsafe
1182 closeFile :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1183 foreign import "libHS_cbits" "fileEOF" unsafe
1184 fileEOF :: FILE_OBJECT -> IO Int{-ret code-}
1185 foreign import "libHS_cbits" "setBuffering" unsafe
1186 setBuffering :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1187 foreign import "libHS_cbits" "flushFile" unsafe
1188 flushFile :: FILE_OBJECT -> IO Int{-ret code-}
1189 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1190 flushConnectedBuf :: FILE_OBJECT -> IO ()
1191 foreign import "libHS_cbits" "getBufferMode" unsafe
1192 getBufferMode :: FILE_OBJECT -> IO Int{-ret code-}
1194 foreign import "libHS_cbits" "seekFile_int64" unsafe
1195 seekFile :: FILE_OBJECT -> Int -> Int64 -> IO Int
1197 foreign import "libHS_cbits" "seekFile" unsafe
1198 seekFile :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1201 foreign import "libHS_cbits" "seekFileP" unsafe
1202 seekFileP :: FILE_OBJECT -> IO Int{-ret code-}
1203 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1204 setTerminalEcho :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1205 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1206 getTerminalEcho :: FILE_OBJECT -> IO Int{-ret code-}
1207 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1208 isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1209 foreign import "libHS_cbits" "setConnectedTo" unsafe
1210 setConnectedTo :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1211 foreign import "libHS_cbits" "ungetChar" unsafe
1212 ungetChar :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1213 foreign import "libHS_cbits" "readChunk" unsafe
1214 readChunk :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1215 foreign import "libHS_cbits" "readChunk" unsafe
1216 readChunkBA :: FILE_OBJECT -> ByteArray Int -> Int -> IO Int{-ret code-}
1217 foreign import "libHS_cbits" "writeBuf" unsafe
1218 writeBuf :: FILE_OBJECT -> Addr -> Int -> IO Int{-ret code-}
1220 foreign import "libHS_cbits" "writeBufBA" unsafe
1221 writeBufBA :: FILE_OBJECT -> ByteArray Int -> Int -> IO Int{-ret code-}
1223 foreign import "libHS_cbits" "getFileFd" unsafe
1224 getFileFd :: FILE_OBJECT -> IO Int{-fd-}
1226 foreign import "libHS_cbits" "fileSize_int64" unsafe
1227 fileSize_int64 :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1229 foreign import "libHS_cbits" "fileSize" unsafe
1230 fileSize :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1233 foreign import "libHS_cbits" "getFilePosn" unsafe
1234 getFilePosn :: FILE_OBJECT -> IO Int
1235 foreign import "libHS_cbits" "setFilePosn" unsafe
1236 setFilePosn :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1237 foreign import "libHS_cbits" "getConnFileFd" unsafe
1238 getConnFileFd :: FILE_OBJECT -> IO Int{-fd-}
1239 foreign import "libHS_cbits" "getLock" unsafe
1240 getLock :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1241 foreign import "libHS_cbits" "openStdFile" unsafe
1242 openStdFile :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1243 foreign import "libHS_cbits" "openFile" unsafe
1244 primOpenFile :: ByteArray Int{-CString-}
1247 -> IO Addr {-file obj-}
1248 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1251 foreign import "libHS_cbits" "setBinaryMode__"
1252 setBinaryMode :: FILE_OBJECT -> Int -> IO Int