2 % (c) The AQUA Project, Glasgow University, 1994-1998
4 \section[IO]{Module @IO@}
6 Implementation of the standard Haskell IO interface, see
7 @http://haskell.org/onlinelibrary/io.html@ for the official
11 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
14 Handle, -- abstract, instance of: Eq, Show.
15 HandlePosn(..), -- abstract, instance of: Eq, Show.
17 IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
18 BufferMode(NoBuffering,LineBuffering,BlockBuffering),
19 SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
21 stdin, stdout, stderr, -- :: Handle
23 openFile, -- :: FilePath -> IOMode -> IO Handle
24 hClose, -- :: Handle -> IO ()
25 hFileSize, -- :: Handle -> IO Integer
26 hIsEOF, -- :: Handle -> IO Bool
29 hSetBuffering, -- :: Handle -> BufferMode -> IO ()
30 hGetBuffering, -- :: Handle -> IO BufferMode
31 hFlush, -- :: Handle -> IO ()
32 hGetPosn, -- :: Handle -> IO HandlePosn
33 hSetPosn, -- :: Handle -> HandlePosn -> IO ()
34 hSeek, -- :: Handle -> SeekMode -> Integer -> IO ()
35 hWaitForInput, -- :: Handle -> Int -> IO Bool
36 hReady, -- :: Handle -> IO Bool
37 hGetChar, -- :: Handle -> IO Char
38 hGetLine, -- :: Handle -> IO [Char]
39 hLookAhead, -- :: Handle -> IO Char
40 hGetContents, -- :: Handle -> IO [Char]
41 hPutChar, -- :: Handle -> Char -> IO ()
42 hPutStr, -- :: Handle -> [Char] -> IO ()
43 hPutStrLn, -- :: Handle -> [Char] -> IO ()
44 hPrint, -- :: Show a => Handle -> a -> IO ()
45 hIsOpen, hIsClosed, -- :: Handle -> IO Bool
46 hIsReadable, hIsWritable, -- :: Handle -> IO Bool
47 hIsSeekable, -- :: Handle -> IO Bool
49 isAlreadyExistsError, isDoesNotExistError, -- :: IOError -> Bool
50 isAlreadyInUseError, isFullError,
51 isEOFError, isIllegalOperation,
52 isPermissionError, isUserError,
54 ioeGetErrorString, -- :: IOError -> String
55 ioeGetHandle, -- :: IOError -> Maybe Handle
56 ioeGetFileName, -- :: IOError -> Maybe FilePath
58 try, -- :: IO a -> IO (Either IOError a)
59 bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
60 bracket_, -- :: IO a -> (a -> IO b) -> IO c -> IO c
62 -- Non-standard extension (but will hopefully become standard with 1.5) is
63 -- to export the Prelude io functions via IO (in addition to exporting them
64 -- from the prelude...for now.)
66 FilePath, -- :: String
68 ioError, -- :: IOError -> IO a
69 userError, -- :: String -> IOError
70 catch, -- :: IO a -> (IOError -> IO a) -> IO a
71 interact, -- :: (String -> String) -> IO ()
73 putChar, -- :: Char -> IO ()
74 putStr, -- :: String -> IO ()
75 putStrLn, -- :: String -> IO ()
76 print, -- :: Show a => a -> IO ()
77 getChar, -- :: IO Char
78 getLine, -- :: IO String
79 getContents, -- :: IO String
80 readFile, -- :: FilePath -> IO String
81 writeFile, -- :: FilePath -> String -> IO ()
82 appendFile, -- :: FilePath -> String -> IO ()
83 readIO, -- :: Read a => String -> IO a
84 readLn, -- :: Read a => IO a
102 import PrelHandle -- much of the real stuff is in here
104 import PrelRead ( readParen, Read(..), reads, lex,
108 import PrelMaybe ( Either(..), Maybe(..) )
109 import PrelAddr ( Addr(..), nullAddr )
110 import PrelByteArr ( ByteArray )
111 import PrelPack ( unpackNBytesAccST )
112 import PrelException ( ioError, catch )
114 #ifndef __PARALLEL_HASKELL__
115 import PrelForeign ( ForeignObj )
118 import Char ( ord, chr )
120 #endif /* ndef __HUGS__ */
124 %*********************************************************
126 \subsection{Simple input operations}
128 %*********************************************************
130 Computation @hReady hdl@ indicates whether at least
131 one item is available for input from handle {\em hdl}.
133 @hWaitForInput@ is the generalisation, wait for \tr{n} milliseconds
134 before deciding whether the Handle has run dry or not.
136 If @hWaitForInput@ finds anything in the Handle's buffer, it immediately returns.
137 If not, it tries to read from the underlying OS handle. Notice that
138 for buffered Handles connected to terminals this means waiting until a complete
142 hReady :: Handle -> IO Bool
143 hReady h = hWaitForInput h 0
145 hWaitForInput :: Handle -> Int -> IO Bool
146 hWaitForInput handle msecs =
147 wantReadableHandle "hWaitForInput" handle $ \ handle_ -> do
148 rc <- inputReady (haFO__ handle_) (msecs::Int) -- ConcHask: SAFE, won't block
152 _ -> constructErrorAndFail "hWaitForInput"
155 @hGetChar hdl@ reads the next character from handle @hdl@,
156 blocking until a character is available.
159 hGetChar :: Handle -> IO Char
161 wantReadableHandle "hGetChar" handle $ \ handle_ -> do
162 let fo = haFO__ handle_
163 intc <- mayBlock fo (fileGetc fo) -- ConcHask: UNSAFE, may block
164 if intc /= ((-1)::Int)
165 then return (chr intc)
166 else constructErrorAndFail "hGetChar"
169 If EOF is reached before EOL is encountered, ignore the
170 EOF and return the partial line. Next attempt at calling
171 hGetLine on the handle will yield an EOF IO exception though.
173 hGetLine :: Handle -> IO String
187 if isEOFError err then
199 @hLookahead hdl@ returns the next character from handle @hdl@
200 without removing it from the input buffer, blocking until a
201 character is available.
204 hLookAhead :: Handle -> IO Char
206 wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
207 let fo = haFO__ handle_
208 intc <- mayBlock fo (fileLookAhead fo) -- ConcHask: UNSAFE, may block
210 then return (chr intc)
211 else constructErrorAndFail "hLookAhead"
216 %*********************************************************
218 \subsection{Getting the entire contents of a handle}
220 %*********************************************************
222 @hGetContents hdl@ returns the list of characters corresponding
223 to the unread portion of the channel or file managed by @hdl@,
224 which is made semi-closed.
227 hGetContents :: Handle -> IO String
228 hGetContents handle =
229 -- can't use wantReadableHandle here, because we want to side effect
231 withHandle handle $ \ handle_ -> do
232 case haType__ handle_ of
233 ErrorHandle theError -> ioError theError
234 ClosedHandle -> ioe_closedHandle "hGetContents" handle
235 SemiClosedHandle -> ioe_closedHandle "hGetContents" handle
236 AppendHandle -> ioError not_readable_error
237 WriteHandle -> ioError not_readable_error
240 To avoid introducing an extra layer of buffering here,
241 we provide three lazy read methods, based on character,
242 line, and block buffering.
244 let handle_' = handle_{ haType__ = SemiClosedHandle }
245 case (haBufferMode__ handle_) of
247 str <- unsafeInterleaveIO (lazyReadLine handle (haFO__ handle_))
248 return (handle_', str)
249 BlockBuffering _ -> do
250 str <- unsafeInterleaveIO (lazyReadBlock handle (haFO__ handle_))
251 return (handle_', str)
253 str <- unsafeInterleaveIO (lazyReadChar handle (haFO__ handle_))
254 return (handle_', str)
257 IOError (Just handle) IllegalOperation "hGetContents"
258 ("handle is not open for reading")
261 Note that someone may close the semi-closed handle (or change its buffering),
262 so each these lazy read functions are pulled on, they have to check whether
263 the handle has indeed been closed.
266 #ifndef __PARALLEL_HASKELL__
267 lazyReadBlock :: Handle -> ForeignObj -> IO String
268 lazyReadLine :: Handle -> ForeignObj -> IO String
269 lazyReadChar :: Handle -> ForeignObj -> IO String
271 lazyReadBlock :: Handle -> Addr -> IO String
272 lazyReadLine :: Handle -> Addr -> IO String
273 lazyReadChar :: Handle -> Addr -> IO String
276 lazyReadBlock handle fo = do
277 buf <- getBufStart fo 0
278 bytes <- mayBlock fo (readBlock fo) -- ConcHask: UNSAFE, may block.
280 -3 -> -- buffering has been turned off, use lazyReadChar instead
281 lazyReadChar handle fo
283 -1 -> -- an error occurred, close the handle
284 withHandle handle $ \ handle_ -> do
285 closeFile (haFO__ handle_) 0{-don't bother flushing-} -- ConcHask: SAFE, won't block.
286 return (handle_ { haType__ = ClosedHandle,
287 haFO__ = nullFile__ },
290 more <- unsafeInterleaveIO (lazyReadBlock handle fo)
291 stToIO (unpackNBytesAccST buf bytes more)
293 lazyReadLine handle fo = do
294 bytes <- mayBlock fo (readLine fo) -- ConcHask: UNSAFE, may block.
296 -3 -> -- buffering has been turned off, use lazyReadChar instead
297 lazyReadChar handle fo
298 -2 -> return "" -- handle closed by someone else, stop reading.
299 -1 -> -- an error occurred, close the handle
300 withHandle handle $ \ handle_ -> do
301 closeFile (haFO__ handle_) 0{- don't bother flushing-} -- ConcHask: SAFE, won't block
302 return (handle_ { haType__ = ClosedHandle,
303 haFO__ = nullFile__ },
306 more <- unsafeInterleaveIO (lazyReadLine handle fo)
307 buf <- getBufStart fo bytes -- ConcHask: won't block
308 stToIO (unpackNBytesAccST buf bytes more)
310 lazyReadChar handle fo = do
311 char <- mayBlock fo (readChar fo) -- ConcHask: UNSAFE, may block.
313 -4 -> -- buffering is now block-buffered, use lazyReadBlock instead
314 lazyReadBlock handle fo
316 -3 -> -- buffering is now line-buffered, use lazyReadLine instead
317 lazyReadLine handle fo
319 -1 -> -- error, silently close handle.
320 withHandle handle $ \ handle_ -> do
321 closeFile (haFO__ handle_) 0{-don't bother flusing-} -- ConcHask: SAFE, won't block
322 return (handle_{ haType__ = ClosedHandle,
323 haFO__ = nullFile__ },
326 more <- unsafeInterleaveIO (lazyReadChar handle fo)
327 return (chr char : more)
332 %*********************************************************
334 \subsection{Simple output functions}
336 %*********************************************************
338 @hPutChar hdl ch@ writes the character @ch@ to the file
339 or channel managed by @hdl@. Characters may be buffered if
340 buffering is enabled for @hdl@
343 hPutChar :: Handle -> Char -> IO ()
345 wantWriteableHandle "hPutChar" handle $ \ handle_ -> do
346 let fo = haFO__ handle_
348 rc <- mayBlock fo (filePutc fo c) -- ConcHask: UNSAFE, may block.
351 else constructErrorAndFail "hPutChar"
355 @hPutStr hdl s@ writes the string @s@ to the file or
356 channel managed by @hdl@, buffering the output if needs be.
359 hPutStr :: Handle -> String -> IO ()
361 wantWriteableHandle "hPutStr" handle $ \ handle_ -> do
362 let fo = haFO__ handle_
364 case haBufferMode__ handle_ of
366 buf <- getWriteableBuf fo
369 writeLines fo buf bsz pos str
370 BlockBuffering _ -> do
371 buf <- getWriteableBuf fo
374 writeBlocks fo buf bsz pos str
379 Going across the border between Haskell and C is relatively costly,
380 so for block writes we pack the character strings on the Haskell-side
381 before passing the external write routine a pointer to the buffer.
386 #ifdef __CONCURRENT_HASKELL__
387 /* See comment in shoveString below for explanation */
388 #warning delayed update of buffer disnae work with killThread
391 #ifndef __PARALLEL_HASKELL__
392 writeLines :: ForeignObj -> Addr -> Int -> Int -> String -> IO ()
394 writeLines :: Addr -> Addr -> Int -> Int -> String -> IO ()
396 writeLines obj buf bufLen initPos s =
398 shoveString :: Int -> [Char] -> IO ()
403 At the end of a buffer write, update the buffer position
404 in the underlying file object, so that if the handle
405 is subsequently dropped by the program, the whole
406 buffer will be properly flushed.
408 There's one case where this delayed up-date of the buffer
409 position can go wrong: if a thread is killed, it might be
410 in the middle of filling up a buffer, with the result that
411 the partial buffer update is lost upon finalisation. Not
412 that killing of threads is supported at the moment.
418 primWriteCharOffAddr buf n x
419 {- Flushing on buffer exhaustion or newlines (even if it isn't the last one) -}
420 if n == bufLen || x == '\n'
422 rc <- mayBlock obj (writeFileObject obj (n + 1)) -- ConcHask: UNSAFE, may block.
424 then shoveString 0 xs
425 else constructErrorAndFail "writeLines"
427 shoveString (n + 1) xs
429 shoveString initPos s
430 #else /* ndef __HUGS__ */
431 #ifndef __PARALLEL_HASKELL__
432 writeLines :: ForeignObj -> Addr -> Int -> Int -> String -> IO ()
434 writeLines :: Addr -> Addr -> Int -> Int -> String -> IO ()
436 writeLines obj buf (I# bufLen) (I# initPos#) s =
438 write_char :: Addr -> Int# -> Char# -> IO ()
439 write_char (A# buf#) n# c# =
441 case (writeCharOffAddr# buf# n# c# s#) of s2# -> (# s2#, () #)
443 shoveString :: Int# -> [Char] -> IO ()
448 At the end of a buffer write, update the buffer position
449 in the underlying file object, so that if the handle
450 is subsequently dropped by the program, the whole
451 buffer will be properly flushed.
453 There's one case where this delayed up-date of the buffer
454 position can go wrong: if a thread is killed, it might be
455 in the middle of filling up a buffer, with the result that
456 the partial buffer update is lost upon finalisation. Not
457 that killing of threads is supported at the moment.
460 setBufWPtr obj (I# n)
464 {- Flushing on buffer exhaustion or newlines (even if it isn't the last one) -}
465 if n ==# bufLen || x `eqChar#` '\n'#
467 rc <- mayBlock obj (writeFileObject obj (I# (n +# 1#))) -- ConcHask: UNSAFE, may block.
469 then shoveString 0# xs
470 else constructErrorAndFail "writeLines"
472 shoveString (n +# 1#) xs
474 shoveString initPos# s
475 #endif /* ndef __HUGS__ */
478 #ifndef __PARALLEL_HASKELL__
479 writeBlocks :: ForeignObj -> Addr -> Int -> Int -> String -> IO ()
481 writeBlocks :: Addr -> Addr -> Int -> Int -> String -> IO ()
483 writeBlocks obj buf bufLen initPos s =
485 shoveString :: Int -> [Char] -> IO ()
490 At the end of a buffer write, update the buffer position
491 in the underlying file object, so that if the handle
492 is subsequently dropped by the program, the whole
493 buffer will be properly flushed.
495 There's one case where this delayed up-date of the buffer
496 position can go wrong: if a thread is killed, it might be
497 in the middle of filling up a buffer, with the result that
498 the partial buffer update is lost upon finalisation. However,
499 by the time killThread is supported, Haskell finalisers are also
500 likely to be in, which means the 'IOFileObject' hack can go
507 primWriteCharOffAddr buf n x
510 rc <- mayBlock obj (writeFileObject obj (n + 1)) -- ConcHask: UNSAFE, may block.
512 then shoveString 0 xs
513 else constructErrorAndFail "writeChunks"
515 shoveString (n + 1) xs
517 shoveString initPos s
518 #else /* ndef __HUGS__ */
519 #ifndef __PARALLEL_HASKELL__
520 writeBlocks :: ForeignObj -> Addr -> Int -> Int -> String -> IO ()
522 writeBlocks :: Addr -> Addr -> Int -> Int -> String -> IO ()
524 writeBlocks obj buf (I# bufLen) (I# initPos#) s =
526 write_char :: Addr -> Int# -> Char# -> IO ()
527 write_char (A# buf#) n# c# =
529 case (writeCharOffAddr# buf# n# c# s#) of s2# -> (# s2#, () #)
531 shoveString :: Int# -> [Char] -> IO ()
536 At the end of a buffer write, update the buffer position
537 in the underlying file object, so that if the handle
538 is subsequently dropped by the program, the whole
539 buffer will be properly flushed.
541 There's one case where this delayed up-date of the buffer
542 position can go wrong: if a thread is killed, it might be
543 in the middle of filling up a buffer, with the result that
544 the partial buffer update is lost upon finalisation. However,
545 by the time killThread is supported, Haskell finalisers are also
546 likely to be in, which means the 'IOFileObject' hack can go
550 setBufWPtr obj (I# n)
556 rc <- mayBlock obj (writeFileObject obj (I# (n +# 1#))) -- ConcHask: UNSAFE, may block.
558 then shoveString 0# xs
559 else constructErrorAndFail "writeChunks"
561 shoveString (n +# 1#) xs
563 shoveString initPos# s
564 #endif /* ndef __HUGS__ */
566 #ifndef __PARALLEL_HASKELL__
567 writeChars :: ForeignObj -> String -> IO ()
569 writeChars :: Addr -> String -> IO ()
571 writeChars _fo "" = return ()
572 writeChars fo (c:cs) = do
573 rc <- mayBlock fo (filePutc fo c) -- ConcHask: UNSAFE, may block.
575 then writeChars fo cs
576 else constructErrorAndFail "writeChars"
580 Computation @hPrint hdl t@ writes the string representation of {\em t}
581 given by the @shows@ function to the file or channel managed by {\em
584 [ Seem to have disappeared from the 1.4 interface - SOF 2/97 ]
587 hPrint :: Show a => Handle -> a -> IO ()
588 hPrint hdl = hPutStrLn hdl . show
591 Derived action @hPutStrLn hdl str@ writes the string \tr{str} to
592 the handle \tr{hdl}, adding a newline at the end.
595 hPutStrLn :: Handle -> String -> IO ()
596 hPutStrLn hndl str = do
603 %*********************************************************
605 \subsection{Try and bracket}
607 %*********************************************************
609 The construct @try comp@ exposes errors which occur within a
610 computation, and which are not fully handled. It always succeeds.
613 try :: IO a -> IO (Either IOError a)
614 try f = catch (do r <- f
618 bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
619 bracket before after m = do
627 -- variant of the above where middle computation doesn't want x
628 bracket_ :: IO a -> (a -> IO b) -> IO c -> IO c
629 bracket_ before after m = do
638 %*********************************************************
640 \subsection{Standard IO}
642 %*********************************************************
644 The Prelude has from Day 1 provided a collection of common
645 IO functions. We define these here, but let the Prelude
649 putChar :: Char -> IO ()
650 putChar c = hPutChar stdout c
652 putStr :: String -> IO ()
653 putStr s = hPutStr stdout s
655 putStrLn :: String -> IO ()
656 putStrLn s = do putStr s
659 print :: Show a => a -> IO ()
660 print x = putStrLn (show x)
663 getChar = hGetChar stdin
666 getLine = hGetLine stdin
668 getContents :: IO String
669 getContents = hGetContents stdin
671 interact :: (String -> String) -> IO ()
672 interact f = do s <- getContents
675 readFile :: FilePath -> IO String
676 readFile name = openFile name ReadMode >>= hGetContents
678 writeFile :: FilePath -> String -> IO ()
679 writeFile name str = do
680 hdl <- openFile name WriteMode
684 appendFile :: FilePath -> String -> IO ()
685 appendFile name str = do
686 hdl <- openFile name AppendMode
690 readLn :: Read a => IO a
691 readLn = do l <- getLine
705 unimp s = error ("IO library: function not implemented: " ++ s)
707 type FILE_STAR = Addr
712 = Handle { name :: FilePath,
713 file :: FILE_STAR, -- C handle
714 mut :: IORef Handle_Mut, -- open/closed/semiclosed
720 = Handle_Mut { state :: HState
724 set_state :: Handle -> HState -> IO ()
725 set_state hdl new_state
726 = writeIORef (mut hdl) (Handle_Mut { state = new_state })
727 get_state :: Handle -> IO HState
729 = readIORef (mut hdl) >>= \m -> return (state m)
731 mkErr :: Handle -> String -> IO a
733 = do mut <- readIORef (mut h)
734 when (state mut /= HClosed)
735 (nh_close (file h) >> set_state h HClosed)
737 ioError (IOError msg)
742 file = primRunST nh_stdin,
743 mut = primRunST (newIORef (Handle_Mut { state = HOpen })),
750 file = primRunST nh_stdout,
751 mut = primRunST (newIORef (Handle_Mut { state = HOpen })),
758 file = primRunST nh_stderr,
759 mut = primRunST (newIORef (Handle_Mut { state = HOpen })),
764 instance Eq Handle where
765 h1 == h2 = file h1 == file h2
767 instance Show Handle where
768 showsPrec _ h = showString ("`" ++ name h ++ "'")
775 data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
776 deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)
778 data BufferMode = NoBuffering | LineBuffering
779 | BlockBuffering (Maybe Int)
780 deriving (Eq, Ord, Read, Show)
782 data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
783 deriving (Eq, Ord, Ix, Bounded, Enum, Read, Show)
785 data HState = HOpen | HSemiClosed | HClosed
789 -- A global variable holding a list of all open handles.
790 -- Each handle is present as many times as it has been opened.
791 -- Any given file is allowed to have _either_ one writeable handle
792 -- or many readable handles in this list. The list is used to
793 -- enforce single-writer multiple reader semantics. It also
794 -- provides a list of handles for System.exitWith to flush and
795 -- close. In order not to have to put all this stuff in the
796 -- Prelude, System.exitWith merely runs prelExitWithAction,
797 -- which is originally Nothing, but which we set to Just ...
798 -- once handles appear in the list.
800 allHandles :: IORef [Handle]
801 allHandles = primRunST (newIORef [])
803 elemWriterHandles :: FilePath -> IO Bool
804 elemAllHandles :: FilePath -> IO Bool
805 addHandle :: Handle -> IO ()
806 delHandle :: Handle -> IO ()
807 cleanupHandles :: IO ()
810 = do hdls <- readIORef allHandles
811 mapM_ cleanupHandle hdls
816 >> nh_errno >>= \_ -> return ()
818 = nh_flush (file h) >> nh_close (file h)
819 >> nh_errno >>= \_ -> return ()
821 elemWriterHandles fname
822 = do hdls <- readIORef allHandles
823 let hdls_w = filter ((/= ReadMode).mode) hdls
824 return (fname `elem` (map name hdls_w))
827 = do hdls <- readIORef allHandles
828 return (fname `elem` (map name hdls))
831 = do cleanup_action <- readIORef prelCleanupAfterRunAction
832 case cleanup_action of
834 -> writeIORef prelCleanupAfterRunAction (Just cleanupHandles)
837 hdls <- readIORef allHandles
838 writeIORef allHandles (hdl : hdls)
841 = do hdls <- readIORef allHandles
842 let hdls' = takeWhile (/= hdl) hdls
843 ++ drop 1 (dropWhile (/= hdl) hdls)
844 writeIORef allHandles hdls'
848 openFile :: FilePath -> IOMode -> IO Handle
852 = (ioError.IOError) "openFile: empty file name"
855 = do not_ok <- elemWriterHandles f
857 then (ioError.IOError)
858 ("openFile: `" ++ f ++ "' in " ++ show mode
859 ++ ": is already open for writing")
860 else openFile_main f mode
863 = do not_ok <- elemAllHandles f
865 then (ioError.IOError)
866 ("openFile: `" ++ f ++ "' in " ++ show mode
867 ++ ": is already open for reading or writing")
868 else openFile_main f mode
871 = openFile_main f mode
874 = copy_String_to_cstring f >>= \nameptr ->
875 nh_open nameptr (mode2num mode) >>= \fh ->
878 then (ioError.IOError)
879 ("openFile: can't open <<" ++ f ++ ">> in " ++ show mode)
880 else do r <- newIORef (Handle_Mut { state = HOpen })
881 let hdl = Handle { name = f, file = fh,
882 mut = r, mode = mode }
886 mode2num :: IOMode -> Int
887 mode2num ReadMode = 0
888 mode2num WriteMode = 1
889 mode2num AppendMode = 2
890 mode2num ReadWriteMode
892 ("openFile <<" ++ f ++ ">>: ReadWriteMode not supported")
894 hClose :: Handle -> IO ()
896 = do mut <- readIORef (mut h)
897 putStrLn ( "hClose: state is " ++ show mut)
898 if state mut == HClosed
900 ("hClose on closed handle " ++ show h)
902 do set_state h HClosed
909 ("hClose: error closing " ++ name h)
911 hGetContents :: Handle -> IO String
914 = mkErr h ("hGetContents on non-ReadMode handle " ++ show h)
916 = do mut <- readIORef (mut h)
917 if state mut /= HOpen
919 ("hGetContents on closed/semiclosed handle " ++ show h)
921 do set_state h HSemiClosed
925 = nh_read f >>= \ci ->
928 else read_all f >>= \rest ->
929 return ((primIntToChar ci):rest)
931 hPutStr :: Handle -> String -> IO ()
934 = mkErr h ("hPutStr on ReadMode handle " ++ show h)
936 = do mut <- readIORef (mut h)
937 if state mut /= HOpen
939 ("hPutStr on closed/semiclosed handle " ++ show h)
940 else write_all (file h) s
945 = nh_write f c >> write_all f cs
947 hFileSize :: Handle -> IO Integer
949 = do sz <- nh_filesize (file h)
952 then return (fromIntegral sz)
953 else mkErr h ("hFileSize on " ++ show h)
955 hIsEOF :: Handle -> IO Bool
957 = do iseof <- nh_iseof (file h)
960 then return (iseof /= 0)
961 else mkErr h ("hIsEOF on " ++ show h)
966 hSetBuffering :: Handle -> BufferMode -> IO ()
967 hSetBuffering = unimp "IO.hSetBuffering"
968 hGetBuffering :: Handle -> IO BufferMode
969 hGetBuffering = unimp "IO.hGetBuffering"
971 hFlush :: Handle -> IO ()
973 = do mut <- readIORef (mut h)
974 if state mut /= HOpen
976 ("hFlush on closed/semiclosed file " ++ name h)
977 else nh_flush (file h)
979 hGetPosn :: Handle -> IO HandlePosn
980 hGetPosn = unimp "IO.hGetPosn"
981 hSetPosn :: HandlePosn -> IO ()
982 hSetPosn = unimp "IO.hSetPosn"
983 hSeek :: Handle -> SeekMode -> Integer -> IO ()
984 hSeek = unimp "IO.hSeek"
985 hWaitForInput :: Handle -> Int -> IO Bool
986 hWaitForInput = unimp "hWaitForInput"
987 hReady :: Handle -> IO Bool
988 hReady h = unimp "hReady" -- hWaitForInput h 0
990 hGetChar :: Handle -> IO Char
992 = nh_read (file h) >>= \ci ->
993 return (primIntToChar ci)
995 hGetLine :: Handle -> IO String
996 hGetLine h = do c <- hGetChar h
997 if c=='\n' then return ""
998 else do cs <- hGetLine h
1001 hLookAhead :: Handle -> IO Char
1002 hLookAhead = unimp "IO.hLookAhead"
1005 hPutChar :: Handle -> Char -> IO ()
1006 hPutChar h c = hPutStr h [c]
1008 hPutStrLn :: Handle -> String -> IO ()
1009 hPutStrLn h s = do { hPutStr h s; hPutChar h '\n' }
1011 hPrint :: Show a => Handle -> a -> IO ()
1012 hPrint h = hPutStrLn h . show
1014 hIsOpen, hIsClosed, hIsReadable, hIsWritable :: Handle -> IO Bool
1015 hIsOpen h = do { s <- get_state h; return (s == HOpen) }
1016 hIsClosed h = do { s <- get_state h; return (s == HClosed) }
1017 hIsReadable h = return (mode h == ReadMode)
1018 hIsWritable h = return (mode h `elem` [WriteMode, AppendMode])
1020 hIsSeekable :: Handle -> IO Bool
1021 hIsSeekable = unimp "IO.hIsSeekable"
1024 isAlreadyExistsError,
1025 isDoesNotExistError,
1026 isAlreadyInUseError,
1030 isUserError :: IOError -> Bool
1032 isIllegalOperation = unimp "IO.isIllegalOperation"
1033 isAlreadyExistsError = unimp "IO.isAlreadyExistsError"
1034 isDoesNotExistError = unimp "IO.isDoesNotExistError"
1035 isAlreadyInUseError = unimp "IO.isAlreadyInUseError"
1036 isFullError = unimp "IO.isFullError"
1037 isEOFError = unimp "IO.isEOFError"
1038 isPermissionError = unimp "IO.isPermissionError"
1039 isUserError = unimp "IO.isUserError"
1042 ioeGetErrorString :: IOError -> String
1043 ioeGetErrorString = unimp "IO.ioeGetErrorString"
1044 ioeGetHandle :: IOError -> Maybe Handle
1045 ioeGetHandle = unimp "IO.ioeGetHandle"
1046 ioeGetFileName :: IOError -> Maybe FilePath
1047 ioeGetFileName = unimp "IO.ioeGetFileName"
1049 try :: IO a -> IO (Either IOError a)
1050 try p = catch (p >>= (return . Right)) (return . Left)
1052 bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
1053 bracket before after m = do
1061 -- variant of the above where middle computation doesn't want x
1062 bracket_ :: IO a -> (a -> IO b) -> IO c -> IO c
1063 bracket_ before after m = do
1071 -- TODO: Hugs/slurpFile
1072 slurpFile = unimp "IO.slurpFile"
1075 #endif /* #ifndef __HUGS__ */