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 PrelByteArr ( ByteArray(..), MutableByteArray(..) )
20 import PrelRead ( Read )
21 import PrelList ( span )
24 import PrelMaybe ( Maybe(..) )
26 import PrelNum ( toBig, Integer(..), Num(..) )
28 import PrelAddr ( Addr, nullAddr )
29 import PrelReal ( toInteger )
30 import PrelPack ( packString )
31 #ifndef __PARALLEL_HASKELL__
32 import PrelWeak ( addForeignFinalizer )
38 #ifndef __PARALLEL_HASKELL__
39 import PrelForeign ( makeForeignObj )
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 {-# INLINE withHandle #-}
67 newHandle :: Handle__ -> IO Handle
69 -- Use MVars for concurrent Haskell
70 newHandle hc = newMVar hc >>= \ h ->
74 %*********************************************************
76 \subsection{@withHandle@ operations}
78 %*********************************************************
80 In the concurrent world, handles are locked during use. This is done
81 by wrapping an MVar around the handle which acts as a mutex over
82 operations on the handle.
84 To avoid races, we use the following bracketing operations. The idea
85 is to obtain the lock, do some operation and replace the lock again,
86 whether the operation succeeded or failed. We also want to handle the
87 case where the thread receives an exception while processing the IO
88 operation: in these cases we also want to relinquish the lock.
90 There are three versions of @withHandle@: corresponding to the three
91 possible combinations of:
93 - the operation may side-effect the handle
94 - the operation may return a result
96 If the operation generates an error or an exception is raised, the
97 orignal handle is always replaced [ this is the case at the moment,
98 but we might want to revisit this in the future --SDM ].
101 withHandle :: Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
102 withHandle (Handle h) act = do
104 (h',v) <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
108 withHandle_ :: Handle -> (Handle__ -> IO a) -> IO a
109 withHandle_ (Handle h) act = do
111 v <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
115 withHandle__ :: Handle -> (Handle__ -> IO Handle__) -> IO ()
116 withHandle__ (Handle h) act = do
118 h' <- catchException (act h_) (\ ex -> putMVar h h_ >> throw ex)
123 nullFile__ is only used for closed handles, plugging it in as a null
124 file object reference.
127 nullFile__ :: FILE_OBJECT
129 #ifndef __PARALLEL_HASKELL__
130 unsafePerformIO (makeForeignObj nullAddr)
136 mkClosedHandle__ :: Handle__
144 mkErrorHandle__ :: IOError -> Handle__
145 mkErrorHandle__ ioe =
153 %*********************************************************
155 \subsection{Handle Finalizers}
157 %*********************************************************
160 foreign import "libHS_cbits" "freeStdFileObject" unsafe
161 freeStdFileObject :: FILE_OBJECT -> IO ()
162 foreign import "libHS_cbits" "freeFileObject" unsafe
163 freeFileObject :: FILE_OBJECT -> IO ()
167 %*********************************************************
169 \subsection[StdHandles]{Standard handles}
171 %*********************************************************
173 Three handles are allocated during program initialisation. The first
174 two manage input or output from the Haskell program's standard input
175 or output channel respectively. The third manages output to the
176 standard error channel. These handles are initially open.
180 stdin, stdout, stderr :: Handle
182 stdout = unsafePerformIO (do
183 rc <- getLock (1::Int) (1::Int) -- ConcHask: SAFE, won't block
185 0 -> newHandle (mkClosedHandle__)
187 fo <- openStdFile (1::Int)
188 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
190 #ifndef __PARALLEL_HASKELL__
191 fo <- makeForeignObj fo
192 addForeignFinalizer fo (freeStdFileObject fo)
196 /* I dont care what the Haskell report says, in an interactive system,
197 * stdout should be unbuffered by default.
201 (bm, bf_size) <- getBMode__ fo
202 mkBuffer__ fo bf_size
204 newHandle (Handle__ fo WriteHandle bm "stdout")
205 _ -> do ioError <- constructError "stdout"
206 newHandle (mkErrorHandle__ ioError)
209 stdin = unsafePerformIO (do
210 rc <- getLock (0::Int) (0::Int) -- ConcHask: SAFE, won't block
212 0 -> newHandle (mkClosedHandle__)
214 fo <- openStdFile (0::Int)
215 (1::Int){-readable-} -- ConcHask: SAFE, won't block
217 #ifndef __PARALLEL_HASKELL__
218 fo <- makeForeignObj fo
219 addForeignFinalizer fo (freeStdFileObject fo)
221 (bm, bf_size) <- getBMode__ fo
222 mkBuffer__ fo bf_size
223 hdl <- newHandle (Handle__ fo ReadHandle bm "stdin")
224 -- when stdin and stdout are both connected to a terminal, ensure
225 -- that anything buffered on stdout is flushed prior to reading from stdin.
227 hConnectTerms stdout hdl
229 _ -> do ioError <- constructError "stdin"
230 newHandle (mkErrorHandle__ ioError)
234 stderr = unsafePerformIO (do
235 rc <- getLock (2::Int) (1::Int){-writeable-} -- ConcHask: SAFE, won't block
237 0 -> newHandle (mkClosedHandle__)
239 fo <- openStdFile (2::Int)
240 (0::Int){-writeable-} -- ConcHask: SAFE, won't block
242 #ifndef __PARALLEL_HASKELL__
243 fo <- makeForeignObj fo
244 addForeignFinalizer fo (freeStdFileObject fo)
246 hdl <- newHandle (Handle__ fo WriteHandle NoBuffering "stderr")
247 -- when stderr and stdout are both connected to a terminal, ensure
248 -- that anything buffered on stdout is flushed prior to writing to
250 hConnectTo stdout hdl
253 _ -> do ioError <- constructError "stderr"
254 newHandle (mkErrorHandle__ ioError)
258 %*********************************************************
260 \subsection[OpeningClosing]{Opening and Closing Files}
262 %*********************************************************
265 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
266 deriving (Eq, Ord, Ix, Enum, Read, Show)
271 deriving (Eq, Read, Show)
273 openFile :: FilePath -> IOMode -> IO Handle
274 openFile fp im = openFileEx fp (TextMode im)
276 openFileEx :: FilePath -> IOModeEx -> IO Handle
279 fo <- primOpenFile (packString f)
281 (binary::Int) -- ConcHask: SAFE, won't block
282 if fo /= nullAddr then do
283 #ifndef __PARALLEL_HASKELL__
284 fo <- makeForeignObj fo
285 addForeignFinalizer fo (freeFileObject fo)
287 (bm, bf_size) <- getBMode__ fo
288 mkBuffer__ fo bf_size
289 newHandle (Handle__ fo htype bm f)
291 constructErrorAndFailWithInfo "openFile" f
295 BinaryMode bmo -> (bmo, 1)
296 TextMode tmo -> (tmo, 0)
306 ReadMode -> ReadHandle
307 WriteMode -> WriteHandle
308 AppendMode -> AppendHandle
309 ReadWriteMode -> ReadWriteHandle
312 Computation $openFile file mode$ allocates and returns a new, open
313 handle to manage the file {\em file}. It manages input if {\em mode}
314 is $ReadMode$, output if {\em mode} is $WriteMode$ or $AppendMode$,
315 and both input and output if mode is $ReadWriteMode$.
317 If the file does not exist and it is opened for output, it should be
318 created as a new file. If {\em mode} is $WriteMode$ and the file
319 already exists, then it should be truncated to zero length. The
320 handle is positioned at the end of the file if {\em mode} is
321 $AppendMode$, and otherwise at the beginning (in which case its
322 internal position is 0).
324 Implementations should enforce, locally to the Haskell process,
325 multiple-reader single-writer locking on files, which is to say that
326 there may either be many handles on the same file which manage input,
327 or just one handle on the file which manages output. If any open or
328 semi-closed handle is managing a file for output, no new handle can be
329 allocated for that file. If any open or semi-closed handle is
330 managing a file for input, new handles can only be allocated if they
331 do not manage output.
333 Two files are the same if they have the same absolute name. An
334 implementation is free to impose stricter conditions.
337 hClose :: Handle -> IO ()
340 withHandle__ handle $ \ handle_ -> do
341 case haType__ handle_ of
342 ErrorHandle theError -> ioError theError
343 ClosedHandle -> return handle_
345 rc <- closeFile (haFO__ handle_)
346 (1::Int){-flush if you can-} -- ConcHask: SAFE, won't block
347 {- We explicitly close a file object so that we can be told
348 if there were any errors. Note that after @hClose@
349 has been performed, the ForeignObj embedded in the Handle
350 is still lying around in the heap, so care is taken
351 to avoid closing the file object when the ForeignObj
352 is finalized. (we overwrite the file ptr in the underlying
353 FileObject with a NULL as part of closeFile())
356 then return (handle_{ haType__ = ClosedHandle,
357 haFO__ = nullFile__ })
358 else constructErrorAndFail "hClose"
362 Computation $hClose hdl$ makes handle {\em hdl} closed. Before the
363 computation finishes, any items buffered for output and not already
364 sent to the operating system are flushed as for $flush$.
366 %*********************************************************
368 \subsection[FileSize]{Detecting the size of a file}
370 %*********************************************************
373 For a handle {\em hdl} which attached to a physical file, $hFileSize
374 hdl$ returns the size of {\em hdl} in terms of the number of items
375 which can be read from {\em hdl}.
378 hFileSize :: Handle -> IO Integer
380 withHandle_ handle $ \ handle_ -> do
381 case haType__ handle_ of
382 ErrorHandle theError -> ioError theError
383 ClosedHandle -> ioe_closedHandle "hFileSize" handle
384 SemiClosedHandle -> ioe_closedHandle "hFileSize" handle
387 mem <- primNewByteArray 8{-sizeof_int64-}
388 rc <- fileSize_int64 (haFO__ handle_) mem -- ConcHask: SAFE, won't block
390 result <- primReadInt64Array mem 0
391 return (primInt64ToInteger result)
393 constructErrorAndFail "hFileSize"
396 -- HACK! We build a unique MP_INT of the right shape to hold
397 -- a single unsigned word, and we let the C routine
398 -- change the data bits
400 case int2Integer# 1# of
402 rc <- fileSize (haFO__ handle_) d -- ConcHask: SAFE, won't block
403 if rc == (0::Int) then
406 constructErrorAndFail "hFileSize"
410 %*********************************************************
412 \subsection[EOF]{Detecting the End of Input}
414 %*********************************************************
417 For a readable handle {\em hdl}, @hIsEOF hdl@ returns
418 @True@ if no further input can be taken from @hdl@ or for a
419 physical file, if the current I/O position is equal to the length of
420 the file. Otherwise, it returns @False@.
423 hIsEOF :: Handle -> IO Bool
425 rc <- mayBlockRead "hIsEOF" handle fileEOF
429 _ -> constructErrorAndFail "hIsEOF"
435 %*********************************************************
437 \subsection[Buffering]{Buffering Operations}
439 %*********************************************************
441 Three kinds of buffering are supported: line-buffering,
442 block-buffering or no-buffering. See @IOBase@ for definition
443 and further explanation of what the type represent.
445 Computation @hSetBuffering hdl mode@ sets the mode of buffering for
446 handle {\em hdl} on subsequent reads and writes.
450 If {\em mode} is @LineBuffering@, line-buffering should be
453 If {\em mode} is @BlockBuffering@ {\em size}, then block-buffering
454 should be enabled if possible. The size of the buffer is {\em n} items
455 if {\em size} is @Just@~{\em n} and is otherwise implementation-dependent.
457 If {\em mode} is @NoBuffering@, then buffering is disabled if possible.
460 If the buffer mode is changed from @BlockBuffering@ or @LineBuffering@
461 to @NoBuffering@, then any items in the output buffer are written to
462 the device, and any items in the input buffer are discarded. The
463 default buffering mode when a handle is opened is
464 implementation-dependent and may depend on the object which is
465 attached to that handle.
468 hSetBuffering :: Handle -> BufferMode -> IO ()
470 hSetBuffering handle mode =
472 BlockBuffering (Just n)
474 (IOError (Just handle)
477 ("illegal buffer size " ++ showsPrec 9 n [])) -- 9 => should be parens'ified.
479 withHandle__ handle $ \ handle_ -> do
480 case haType__ handle_ of
481 ErrorHandle theError -> ioError theError
482 ClosedHandle -> ioe_closedHandle "hSetBuffering" handle
485 - we flush the old buffer regardless of whether
486 the new buffer could fit the contents of the old buffer
488 - allow a handle's buffering to change even if IO has
489 occurred (ANSI C spec. does not allow this, nor did
490 the previous implementation of IO.hSetBuffering).
491 - a non-standard extension is to allow the buffering
492 of semi-closed handles to change [sof 6/98]
494 let fo = haFO__ handle_
495 rc <- mayBlock fo (setBuffering fo bsize) -- ConcHask: UNSAFE, may block
498 return (handle_{ haBufferMode__ = mode })
500 -- Note: failure to change the buffer size will cause old buffer to be flushed.
501 constructErrorAndFail "hSetBuffering"
507 BlockBuffering Nothing -> -2
508 BlockBuffering (Just n) -> n
511 The action @hFlush hdl@ causes any items buffered for output
512 in handle {\em hdl} to be sent immediately to the operating
516 hFlush :: Handle -> IO ()
518 wantWriteableHandle "hFlush" handle $ \ handle_ -> do
519 let fo = haFO__ handle_
520 rc <- mayBlock fo (flushFile fo) -- ConcHask: UNSAFE, may block
524 constructErrorAndFail "hFlush"
529 %*********************************************************
531 \subsection[Seeking]{Repositioning Handles}
533 %*********************************************************
538 Handle -- Q: should this be a weak or strong ref. to the handle?
539 -- [what's the winning argument for it not being strong? --sof]
542 instance Eq HandlePosn where
543 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
545 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
546 -- We represent it as an Integer on the Haskell side, but
547 -- cheat slightly in that hGetPosn calls upon a C helper
548 -- that reports the position back via (merely) an Int.
549 type HandlePosition = Integer
551 mkHandlePosn :: Handle -> HandlePosition -> HandlePosn
552 mkHandlePosn h p = HandlePosn h p
554 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
555 deriving (Eq, Ord, Ix, Enum, Read, Show)
558 Computation @hGetPosn hdl@ returns the current I/O
559 position of {\em hdl} as an abstract position. Computation
560 $hSetPosn p$ sets the position of {\em hdl}
561 to a previously obtained position {\em p}.
564 hGetPosn :: Handle -> IO HandlePosn
566 wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
567 posn <- getFilePosn (haFO__ handle_) -- ConcHask: SAFE, won't block
568 if posn /= -1 then do
569 return (mkHandlePosn handle (fromInt posn))
571 constructErrorAndFail "hGetPosn"
573 hSetPosn :: HandlePosn -> IO ()
574 hSetPosn (HandlePosn handle i@(S# _)) = hSetPosn (HandlePosn handle (toBig i))
575 hSetPosn (HandlePosn handle (J# s# d#)) =
576 wantSeekableHandle "hSetPosn" handle $ \ handle_ -> do
577 -- not as silly as it looks: the handle may have been closed in the meantime.
578 let fo = haFO__ handle_
579 rc <- mayBlock fo (setFilePosn fo (I# s#) d#) -- ConcHask: UNSAFE, may block
583 constructErrorAndFail "hSetPosn"
586 The action @hSeek hdl mode i@ sets the position of handle
587 @hdl@ depending on @mode@. If @mode@ is
589 * AbsoluteSeek - The position of @hdl@ is set to @i@.
590 * RelativeSeek - The position of @hdl@ is set to offset @i@ from
591 the current position.
592 * SeekFromEnd - The position of @hdl@ is set to offset @i@ from
595 Some handles may not be seekable (see @hIsSeekable@), or only
596 support a subset of the possible positioning operations (e.g. it may
597 only be possible to seek to the end of a tape, or to a positive
598 offset from the beginning or current position).
600 It is not possible to set a negative I/O position, or for a physical
601 file, an I/O position beyond the current end-of-file.
604 - when seeking using @SeekFromEnd@, positive offsets (>=0) means
605 seeking at or past EOF.
606 - relative seeking on buffered handles can lead to non-obvious results.
609 hSeek :: Handle -> SeekMode -> Integer -> IO ()
611 hSeek handle mode offset =
612 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
613 let fo = haFO__ handle_
614 rc <- mayBlock fo (seekFile fo whence (primIntegerToInt64 offset)) -- ConcHask: UNSAFE, may block
616 hSeek handle mode i@(S# _) = hSeek handle mode (toBig i)
617 hSeek handle mode (J# s# d#) =
618 wantSeekableHandle "hSeek" handle $ \ handle_ -> do
619 let fo = haFO__ handle_
620 rc <- mayBlock fo (seekFile fo whence (I# s#) d#) -- ConcHask: UNSAFE, may block
625 constructErrorAndFail "hSeek"
628 whence = case mode of
634 %*********************************************************
636 \subsection[Query]{Handle Properties}
638 %*********************************************************
640 A number of operations return information about the properties of a
641 handle. Each of these operations returns $True$ if the
642 handle has the specified property, and $False$
645 Computation $hIsBlockBuffered hdl$ returns $( False, Nothing )$ if
646 {\em hdl} is not block-buffered. Otherwise it returns
647 $( True, size )$, where {\em size} is $Nothing$ for default buffering, and
648 $( Just n )$ for block-buffering of {\em n} bytes.
651 hIsOpen :: Handle -> IO Bool
653 withHandle_ handle $ \ handle_ -> do
654 case haType__ handle_ of
655 ErrorHandle theError -> ioError theError
656 ClosedHandle -> return False
657 SemiClosedHandle -> return False
660 hIsClosed :: Handle -> IO Bool
662 withHandle_ handle $ \ handle_ -> do
663 case haType__ handle_ of
664 ErrorHandle theError -> ioError theError
665 ClosedHandle -> return True
668 {- not defined, nor exported, but mentioned
669 here for documentation purposes:
671 hSemiClosed :: Handle -> IO Bool
675 return (not (ho || hc))
678 hIsReadable :: Handle -> IO Bool
680 withHandle_ handle $ \ handle_ -> do
681 case haType__ handle_ of
682 ErrorHandle theError -> ioError theError
683 ClosedHandle -> ioe_closedHandle "hIsReadable" handle
684 SemiClosedHandle -> ioe_closedHandle "hIsReadable" handle
685 htype -> return (isReadable htype)
687 isReadable ReadHandle = True
688 isReadable ReadWriteHandle = True
691 hIsWritable :: Handle -> IO Bool
693 withHandle_ handle $ \ handle_ -> do
694 case haType__ handle_ of
695 ErrorHandle theError -> ioError theError
696 ClosedHandle -> ioe_closedHandle "hIsWritable" handle
697 SemiClosedHandle -> ioe_closedHandle "hIsWritable" handle
698 htype -> return (isWritable htype)
700 isWritable AppendHandle = True
701 isWritable WriteHandle = True
702 isWritable ReadWriteHandle = True
706 #ifndef __PARALLEL_HASKELL__
707 getBMode__ :: ForeignObj -> IO (BufferMode, Int)
709 getBMode__ :: Addr -> IO (BufferMode, Int)
712 rc <- getBufferMode fo -- ConcHask: SAFE, won't block
714 0 -> return (NoBuffering, 0)
715 -1 -> return (LineBuffering, default_buffer_size)
716 -2 -> return (BlockBuffering Nothing, default_buffer_size)
717 -3 -> return (NoBuffering, 0) -- only happens on un-stat()able files.
718 n -> return (BlockBuffering (Just n), n)
720 default_buffer_size :: Int
721 default_buffer_size = (const_BUFSIZ - 1)
724 Querying how a handle buffers its data:
727 hGetBuffering :: Handle -> IO BufferMode
728 hGetBuffering handle =
729 withHandle_ handle $ \ handle_ -> do
730 case haType__ handle_ of
731 ErrorHandle theError -> ioError theError
732 ClosedHandle -> ioe_closedHandle "hGetBuffering" handle
735 We're being non-standard here, and allow the buffering
736 of a semi-closed handle to be queried. -- sof 6/98
738 return (haBufferMode__ handle_) -- could be stricter..
742 hIsSeekable :: Handle -> IO Bool
744 withHandle_ handle $ \ handle_ -> do
745 case haType__ handle_ of
746 ErrorHandle theError -> ioError theError
747 ClosedHandle -> ioe_closedHandle "hIsSeekable" handle
748 SemiClosedHandle -> ioe_closedHandle "hIsSeekable" handle
749 AppendHandle -> return False
751 rc <- seekFileP (haFO__ handle_) -- ConcHask: SAFE, won't block
755 _ -> constructErrorAndFail "hIsSeekable"
759 %*********************************************************
761 \subsection{Changing echo status}
763 %*********************************************************
765 Non-standard GHC extension is to allow the echoing status
766 of a handles connected to terminals to be reconfigured:
769 hSetEcho :: Handle -> Bool -> IO ()
770 hSetEcho handle on = do
771 isT <- hIsTerminalDevice handle
775 withHandle_ handle $ \ handle_ -> do
776 case haType__ handle_ of
777 ErrorHandle theError -> ioError theError
778 ClosedHandle -> ioe_closedHandle "hSetEcho" handle
780 rc <- setTerminalEcho (haFO__ handle_) (if on then 1 else 0) -- ConcHask: SAFE, won't block
783 else constructErrorAndFail "hSetEcho"
785 hGetEcho :: Handle -> IO Bool
787 isT <- hIsTerminalDevice handle
791 withHandle_ handle $ \ handle_ -> do
792 case haType__ handle_ of
793 ErrorHandle theError -> ioError theError
794 ClosedHandle -> ioe_closedHandle "hGetEcho" handle
796 rc <- getTerminalEcho (haFO__ handle_) -- ConcHask: SAFE, won't block
800 _ -> constructErrorAndFail "hSetEcho"
802 hIsTerminalDevice :: Handle -> IO Bool
803 hIsTerminalDevice handle = do
804 withHandle_ handle $ \ handle_ -> do
805 case haType__ handle_ of
806 ErrorHandle theError -> ioError theError
807 ClosedHandle -> ioe_closedHandle "hIsTerminalDevice" handle
809 rc <- isTerminalDevice (haFO__ handle_) -- ConcHask: SAFE, won't block
813 _ -> constructErrorAndFail "hIsTerminalDevice"
817 hConnectTerms :: Handle -> Handle -> IO ()
818 hConnectTerms hW hR = hConnectHdl_ hW hR 1{-check if they're both coming connected to ttys-}
820 hConnectTo :: Handle -> Handle -> IO ()
821 hConnectTo hW hR = hConnectHdl_ hW hR 0{-connect regardless-}
823 hConnectHdl_ :: Handle -> Handle -> Int -> IO ()
824 hConnectHdl_ hW hR is_tty =
825 wantRWHandle "hConnectTo" hW $ \ hW_ ->
826 wantRWHandle "hConnectTo" hR $ \ hR_ -> do
827 setConnectedTo (haFO__ hR_) (haFO__ hW_) is_tty -- ConcHask: SAFE, won't block
829 #ifndef __PARALLEL_HASKELL__
830 #define FILE_OBJECT ForeignObj
832 #define FILE_OBJECT Addr
837 As an extension, we also allow characters to be pushed back.
838 Like ANSI C stdio, we guarantee no more than one character of
839 pushback. (For unbuffered channels, the (default) push-back limit is
843 hUngetChar :: Handle -> Char -> IO ()
844 hUngetChar handle c =
845 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
846 rc <- ungetChar (haFO__ handle_) c -- ConcHask: SAFE, won't block
848 then constructErrorAndFail "hUngetChar"
854 Hoisting files in in one go is sometimes useful, so we support
855 this as an extension:
858 -- in one go, read file into an externally allocated buffer.
859 slurpFile :: FilePath -> IO (Addr, Int)
861 handle <- openFile fname ReadMode
862 sz <- hFileSize handle
863 if sz > toInteger (maxBound::Int) then
864 ioError (userError "slurpFile: file too big")
866 let sz_i = fromInteger sz
867 chunk <- allocMemory__ sz_i
871 constructErrorAndFail "slurpFile"
873 rc <- withHandle_ handle ( \ handle_ -> do
874 let fo = haFO__ handle_
875 mayBlock fo (readChunk fo chunk 0 sz_i) -- ConcHask: UNSAFE, may block.
879 then constructErrorAndFail "slurpFile"
880 else return (chunk, rc)
882 #ifndef __HUGS__ /* Hugs' Prelude doesn't need this */
883 hFillBufBA :: Handle -> MutableByteArray RealWorld a -> Int -> IO Int
884 hFillBufBA handle buf sz
885 | sz <= 0 = ioError (IOError (Just handle)
888 ("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
889 | otherwise = hFillBuf' sz 0
891 hFillBuf' sz len = do
892 r <- mayBlockRead "hFillBufBA" handle (\fo -> readChunkBA fo buf len sz)
893 if r >= sz || r == 0 -- r == 0 indicates EOF
895 else hFillBuf' (sz-r) (len+r)
898 hFillBuf :: Handle -> Addr -> Int -> IO Int
899 hFillBuf handle buf sz
900 | sz <= 0 = ioError (IOError (Just handle)
903 ("illegal buffer size " ++ showsPrec 9 sz []))
904 -- 9 => should be parens'ified.
905 | otherwise = hFillBuf' sz 0
907 hFillBuf' sz len = do
908 r <- mayBlockRead "hFillBuf" handle (\fo -> readChunk fo buf len sz)
909 if r >= sz || r == 0 -- r == 0 indicates EOF
911 else hFillBuf' (sz-r) (len+r)
914 The @hPutBuf hdl buf len@ action writes an already packed sequence of
915 bytes to the file/channel managed by @hdl@ - non-standard.
918 hPutBuf :: Handle -> Addr -> Int -> IO ()
919 hPutBuf handle buf sz
920 | sz <= 0 = ioError (IOError (Just handle)
923 ("illegal buffer size " ++ showsPrec 9 sz []))
924 -- 9 => should be parens'ified.
925 | otherwise = hPutBuf' sz 0
928 r <- mayBlockWrite "hPutBuf" handle (\fo -> writeBuf fo buf len sz)
931 else hPutBuf' (sz-r) (len+r) -- <= sz indicates blocking
933 #ifndef __HUGS__ /* An_ one Hugs doesn't provide */
934 hPutBufBA :: Handle -> MutableByteArray RealWorld a -> Int -> IO ()
935 hPutBufBA handle buf sz
936 | sz <= 0 = ioError (IOError (Just handle)
939 ("illegal buffer size " ++ showsPrec 9 sz []))
940 -- 9 => should be parens'ified.
941 | otherwise = hPutBuf' sz 0
944 r <- mayBlockWrite "hPutBufBA" handle (\fo -> writeBufBA fo buf len sz)
947 else hPutBuf' (sz-r) (len+r) -- <= sz indicates blocking
951 Sometimes it's useful to get at the file descriptor that
952 the Handle contains..
955 getHandleFd :: Handle -> IO Int
957 withHandle_ handle $ \ handle_ -> do
958 case (haType__ handle_) of
959 ErrorHandle theError -> ioError theError
960 ClosedHandle -> ioe_closedHandle "getHandleFd" handle
962 fd <- getFileFd (haFO__ handle_)
967 %*********************************************************
969 \subsection{Miscellaneous}
971 %*********************************************************
973 These three functions are meant to get things out of @IOErrors@.
978 ioeGetFileName :: IOError -> Maybe FilePath
979 ioeGetErrorString :: IOError -> String
980 ioeGetHandle :: IOError -> Maybe Handle
982 ioeGetHandle (IOError h _ _ _) = h
983 ioeGetErrorString (IOError _ iot _ str) =
988 ioeGetFileName (IOError _ _ _ str) =
989 case span (/=':') str of
995 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
996 PrelMain.mainIO) and report them - topHandler is the exception
997 handler they should use for this:
1000 -- make sure we handle errors while reporting the error!
1001 -- (e.g. evaluating the string passed to 'error' might generate
1002 -- another error, etc.)
1003 topHandler :: Bool -> Exception -> IO ()
1004 topHandler bombOut err = catchException (real_handler bombOut err) (topHandler bombOut)
1006 real_handler :: Bool -> Exception -> IO ()
1007 real_handler bombOut ex =
1009 AsyncException StackOverflow -> reportStackOverflow bombOut
1010 ErrorCall s -> reportError bombOut s
1011 other -> reportError bombOut (showsPrec 0 other "\n")
1013 reportStackOverflow :: Bool -> IO ()
1014 reportStackOverflow bombOut = do
1015 (hFlush stdout) `catchException` (\ _ -> return ())
1016 callStackOverflowHook
1022 reportError :: Bool -> String -> IO ()
1023 reportError bombOut str = do
1024 (hFlush stdout) `catchException` (\ _ -> return ())
1025 let bs@(ByteArray _ len _) = packString str
1026 writeErrString addrOf_ErrorHdrHook bs len
1032 foreign label "ErrorHdrHook"
1033 addrOf_ErrorHdrHook :: Addr
1035 foreign import ccall "writeErrString__" unsafe
1036 writeErrString :: Addr -> ByteArray Int -> Int -> IO ()
1038 foreign import ccall "stackOverflow"
1039 callStackOverflowHook :: IO ()
1041 foreign import ccall "stg_exit"
1042 stg_exit :: Int -> IO ()
1046 A number of operations want to get at a readable or writeable handle, and fail
1050 wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1051 wantReadableHandle fun handle act =
1052 withHandle_ handle $ \ handle_ -> do
1053 case haType__ handle_ of
1054 ErrorHandle theError -> ioError theError
1055 ClosedHandle -> ioe_closedHandle fun handle
1056 SemiClosedHandle -> ioe_closedHandle fun handle
1057 AppendHandle -> ioError not_readable_error
1058 WriteHandle -> ioError not_readable_error
1061 not_readable_error =
1062 IOError (Just handle) IllegalOperation fun
1063 ("handle is not open for reading")
1065 wantWriteableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1066 wantWriteableHandle fun handle act =
1067 withHandle_ handle $ \ handle_ -> do
1068 case haType__ handle_ of
1069 ErrorHandle theError -> ioError theError
1070 ClosedHandle -> ioe_closedHandle fun handle
1071 SemiClosedHandle -> ioe_closedHandle fun handle
1072 ReadHandle -> ioError not_writeable_error
1075 not_writeable_error =
1076 IOError (Just handle) IllegalOperation fun
1077 ("handle is not open for writing")
1079 wantRWHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1080 wantRWHandle fun handle act =
1081 withHandle_ handle $ \ handle_ -> do
1082 case haType__ handle_ of
1083 ErrorHandle theError -> ioError theError
1084 ClosedHandle -> ioe_closedHandle fun handle
1085 SemiClosedHandle -> ioe_closedHandle fun handle
1088 wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
1089 wantSeekableHandle fun handle act =
1090 withHandle_ handle $ \ handle_ -> do
1091 case haType__ handle_ of
1092 ErrorHandle theError -> ioError theError
1093 ClosedHandle -> ioe_closedHandle fun handle
1094 SemiClosedHandle -> ioe_closedHandle fun handle
1097 not_seekable_error =
1098 IOError (Just handle)
1099 IllegalOperation fun
1100 ("handle is not seekable")
1104 Internal function for creating an @IOError@ representing the
1105 access to a closed file.
1108 ioe_closedHandle :: String -> Handle -> IO a
1109 ioe_closedHandle fun h = ioError (IOError (Just h) IllegalOperation fun "handle is closed")
1112 Internal helper functions for Concurrent Haskell implementation
1116 #ifndef __PARALLEL_HASKELL__
1117 mayBlock :: ForeignObj -> IO Int -> IO Int
1119 mayBlock :: Addr -> IO Int -> IO Int
1122 mayBlock fo act = do
1125 -5 -> do -- (possibly blocking) read
1128 mayBlock fo act -- input available, re-try
1129 -6 -> do -- (possibly blocking) write
1132 mayBlock fo act -- output possible
1133 -7 -> do -- (possibly blocking) write on connected handle
1134 fd <- getConnFileFd fo
1136 mayBlock fo act -- output possible
1145 mayBlockRead :: String -> Handle -> (ForeignObj -> IO Int) -> IO Int
1146 mayBlockRead fname handle fn = do
1147 r <- wantReadableHandle fname handle $ \ handle_ -> do
1148 let fo = haFO__ handle_
1151 -5 -> do -- (possibly blocking) read
1153 return (BlockRead fd)
1154 -6 -> do -- (possibly blocking) write
1156 return (BlockWrite fd)
1157 -7 -> do -- (possibly blocking) write on connected handle
1158 fd <- getConnFileFd fo
1159 return (BlockWrite fd)
1162 then return (NoBlock rc)
1163 else constructErrorAndFail fname
1167 mayBlockRead fname handle fn
1170 mayBlockRead fname handle fn
1171 NoBlock c -> return c
1173 mayBlockWrite :: String -> Handle -> (ForeignObj -> IO Int) -> IO Int
1174 mayBlockWrite fname handle fn = do
1175 r <- wantWriteableHandle fname handle $ \ handle_ -> do
1176 let fo = haFO__ handle_
1179 -5 -> do -- (possibly blocking) read
1181 return (BlockRead fd)
1182 -6 -> do -- (possibly blocking) write
1184 return (BlockWrite fd)
1185 -7 -> do -- (possibly blocking) write on connected handle
1186 fd <- getConnFileFd fo
1187 return (BlockWrite fd)
1190 then return (NoBlock rc)
1191 else constructErrorAndFail fname
1195 mayBlockWrite fname handle fn
1198 mayBlockWrite fname handle fn
1199 NoBlock c -> return c
1202 Foreign import declarations of helper functions:
1207 type Bytes = PrimByteArray RealWorld
1209 type Bytes = ByteArray#
1212 foreign import "libHS_cbits" "inputReady" unsafe
1213 inputReady :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1214 foreign import "libHS_cbits" "fileGetc" unsafe
1215 fileGetc :: FILE_OBJECT -> IO Int
1216 foreign import "libHS_cbits" "fileLookAhead" unsafe
1217 fileLookAhead :: FILE_OBJECT -> IO Int
1218 foreign import "libHS_cbits" "readBlock" unsafe
1219 readBlock :: FILE_OBJECT -> IO Int
1220 foreign import "libHS_cbits" "readLine" unsafe
1221 readLine :: FILE_OBJECT -> IO Int
1222 foreign import "libHS_cbits" "readChar" unsafe
1223 readChar :: FILE_OBJECT -> IO Int
1224 foreign import "libHS_cbits" "writeFileObject" unsafe
1225 writeFileObject :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1226 foreign import "libHS_cbits" "filePutc" unsafe
1227 filePutc :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1228 foreign import "libHS_cbits" "getBufStart" unsafe
1229 getBufStart :: FILE_OBJECT -> Int -> IO Addr
1230 foreign import "libHS_cbits" "getWriteableBuf" unsafe
1231 getWriteableBuf :: FILE_OBJECT -> IO Addr
1232 foreign import "libHS_cbits" "getBufWPtr" unsafe
1233 getBufWPtr :: FILE_OBJECT -> IO Int
1234 foreign import "libHS_cbits" "setBufWPtr" unsafe
1235 setBufWPtr :: FILE_OBJECT -> Int -> IO ()
1236 foreign import "libHS_cbits" "closeFile" unsafe
1237 closeFile :: FILE_OBJECT -> Int{-Flush-} -> IO Int{-ret code-}
1238 foreign import "libHS_cbits" "fileEOF" unsafe
1239 fileEOF :: FILE_OBJECT -> IO Int{-ret code-}
1240 foreign import "libHS_cbits" "setBuffering" unsafe
1241 setBuffering :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1242 foreign import "libHS_cbits" "flushFile" unsafe
1243 flushFile :: FILE_OBJECT -> IO Int{-ret code-}
1244 foreign import "libHS_cbits" "flushConnectedBuf" unsafe
1245 flushConnectedBuf :: FILE_OBJECT -> IO ()
1246 foreign import "libHS_cbits" "getBufferMode" unsafe
1247 getBufferMode :: FILE_OBJECT -> IO Int{-ret code-}
1249 foreign import "libHS_cbits" "seekFile_int64" unsafe
1250 seekFile :: FILE_OBJECT -> Int -> Int64 -> IO Int
1252 foreign import "libHS_cbits" "seekFile" unsafe
1253 seekFile :: FILE_OBJECT -> Int -> Int -> Bytes -> IO Int
1256 foreign import "libHS_cbits" "seekFileP" unsafe
1257 seekFileP :: FILE_OBJECT -> IO Int{-ret code-}
1258 foreign import "libHS_cbits" "setTerminalEcho" unsafe
1259 setTerminalEcho :: FILE_OBJECT -> Int -> IO Int{-ret code-}
1260 foreign import "libHS_cbits" "getTerminalEcho" unsafe
1261 getTerminalEcho :: FILE_OBJECT -> IO Int{-ret code-}
1262 foreign import "libHS_cbits" "isTerminalDevice" unsafe
1263 isTerminalDevice :: FILE_OBJECT -> IO Int{-ret code-}
1264 foreign import "libHS_cbits" "setConnectedTo" unsafe
1265 setConnectedTo :: FILE_OBJECT -> FILE_OBJECT -> Int -> IO ()
1266 foreign import "libHS_cbits" "ungetChar" unsafe
1267 ungetChar :: FILE_OBJECT -> Char -> IO Int{-ret code-}
1268 foreign import "libHS_cbits" "readChunk" unsafe
1269 readChunk :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1270 foreign import "libHS_cbits" "readChunk" unsafe
1271 readChunkBA :: FILE_OBJECT -> MutableByteArray s a -> Int -> Int -> IO Int{-ret code-}
1272 foreign import "libHS_cbits" "writeBuf" unsafe
1273 writeBuf :: FILE_OBJECT -> Addr -> Int -> Int -> IO Int{-ret code-}
1275 foreign import "libHS_cbits" "writeBufBA" unsafe
1276 writeBufBA :: FILE_OBJECT -> MutableByteArray s a -> Int -> Int -> IO Int{-ret code-}
1278 foreign import "libHS_cbits" "getFileFd" unsafe
1279 getFileFd :: FILE_OBJECT -> IO Int{-fd-}
1281 foreign import "libHS_cbits" "fileSize_int64" unsafe
1282 fileSize_int64 :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1284 foreign import "libHS_cbits" "fileSize" unsafe
1285 fileSize :: FILE_OBJECT -> Bytes -> IO Int{-ret code-}
1288 foreign import "libHS_cbits" "getFilePosn" unsafe
1289 getFilePosn :: FILE_OBJECT -> IO Int
1290 foreign import "libHS_cbits" "setFilePosn" unsafe
1291 setFilePosn :: FILE_OBJECT -> Int -> ByteArray# -> IO Int
1292 foreign import "libHS_cbits" "getConnFileFd" unsafe
1293 getConnFileFd :: FILE_OBJECT -> IO Int{-fd-}
1294 foreign import "libHS_cbits" "getLock" unsafe
1295 getLock :: Int{-Fd-} -> Int{-exclusive-} -> IO Int{-return code-}
1296 foreign import "libHS_cbits" "openStdFile" unsafe
1297 openStdFile :: Int{-fd-} -> Int{-Readable?-} -> IO Addr{-file obj-}
1298 foreign import "libHS_cbits" "openFile" unsafe
1299 primOpenFile :: ByteArray Int{-CString-}
1302 -> IO Addr {-file obj-}
1303 foreign import "libHS_cbits" "const_BUFSIZ" unsafe
1306 foreign import "libHS_cbits" "setBinaryMode__"
1307 setBinaryMode :: FILE_OBJECT -> Int -> IO Int