4 , NondecreasingIndentation
6 {-# OPTIONS_GHC -fno-warn-unused-matches #-}
8 -----------------------------------------------------------------------------
10 -- Module : GHC.IO.Handle
11 -- Copyright : (c) The University of Glasgow, 1994-2009
12 -- License : see libraries/base/LICENSE
14 -- Maintainer : libraries@haskell.org
15 -- Stability : provisional
16 -- Portability : non-portable
18 -- External API for GHC's Handle implementation
20 -----------------------------------------------------------------------------
22 module GHC.IO.Handle (
26 mkFileHandle, mkDuplexHandle,
28 hFileSize, hSetFileSize, hIsEOF, hLookAhead,
29 hSetBuffering, hSetBinaryMode, hSetEncoding, hGetEncoding,
30 hFlush, hFlushAll, hDuplicate, hDuplicateTo,
34 HandlePosition, HandlePosn(..), hGetPosn, hSetPosn,
35 SeekMode(..), hSeek, hTell,
37 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,
38 hSetEcho, hGetEcho, hIsTerminalDevice,
40 hSetNewlineMode, Newline(..), NewlineMode(..), nativeNewline,
41 noNewlineTranslation, universalNewlineMode, nativeNewlineMode,
45 hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,
47 hGetBuf, hGetBufNonBlocking, hPutBuf, hPutBufNonBlocking
51 import GHC.IO.Exception
52 import GHC.IO.Encoding
54 import GHC.IO.BufferedIO ( BufferedIO )
55 import GHC.IO.Device as IODevice
56 import GHC.IO.Handle.Types
57 import GHC.IO.Handle.Internals
58 import GHC.IO.Handle.Text
59 import qualified GHC.IO.BufferedIO as Buffered
72 -- ---------------------------------------------------------------------------
75 -- | Computation 'hClose' @hdl@ makes handle @hdl@ closed. Before the
76 -- computation finishes, if @hdl@ is writable its buffer is flushed as
78 -- Performing 'hClose' on a handle that has already been closed has no effect;
79 -- doing so is not an error. All other operations on a closed handle will fail.
80 -- If 'hClose' fails for any reason, any further operations (apart from
81 -- 'hClose') on the handle will still fail as if @hdl@ had been successfully
84 hClose :: Handle -> IO ()
85 hClose h@(FileHandle _ m) = do
87 hClose_maybethrow mb_exc h
88 hClose h@(DuplexHandle _ r w) = do
89 excs <- mapM (hClose' h) [r,w]
90 hClose_maybethrow (listToMaybe (catMaybes excs)) h
92 hClose_maybethrow :: Maybe SomeException -> Handle -> IO ()
93 hClose_maybethrow Nothing h = return ()
94 hClose_maybethrow (Just e) h = hClose_rethrow e h
96 hClose_rethrow :: SomeException -> Handle -> IO ()
98 case fromException e of
99 Just ioe -> ioError (augmentIOError ioe "hClose" h)
102 hClose' :: Handle -> MVar Handle__ -> IO (Maybe SomeException)
103 hClose' h m = withHandle' "hClose" h m $ hClose_help
105 -----------------------------------------------------------------------------
106 -- Detecting and changing the size of a file
108 -- | For a handle @hdl@ which attached to a physical file,
109 -- 'hFileSize' @hdl@ returns the size of that file in 8-bit bytes.
111 hFileSize :: Handle -> IO Integer
113 withHandle_ "hFileSize" handle $ \ handle_@Handle__{haDevice=dev} -> do
114 case haType handle_ of
115 ClosedHandle -> ioe_closedHandle
116 SemiClosedHandle -> ioe_closedHandle
117 _ -> do flushWriteBuffer handle_
118 r <- IODevice.getSize dev
121 else ioException (IOError Nothing InappropriateType "hFileSize"
122 "not a regular file" Nothing Nothing)
125 -- | 'hSetFileSize' @hdl@ @size@ truncates the physical file with handle @hdl@ to @size@ bytes.
127 hSetFileSize :: Handle -> Integer -> IO ()
128 hSetFileSize handle size =
129 withHandle_ "hSetFileSize" handle $ \ handle_@Handle__{haDevice=dev} -> do
130 case haType handle_ of
131 ClosedHandle -> ioe_closedHandle
132 SemiClosedHandle -> ioe_closedHandle
133 _ -> do flushWriteBuffer handle_
134 IODevice.setSize dev size
137 -- ---------------------------------------------------------------------------
138 -- Detecting the End of Input
140 -- | For a readable handle @hdl@, 'hIsEOF' @hdl@ returns
141 -- 'True' if no further input can be taken from @hdl@ or for a
142 -- physical file, if the current I\/O position is equal to the length of
143 -- the file. Otherwise, it returns 'False'.
145 -- NOTE: 'hIsEOF' may block, because it has to attempt to read from
146 -- the stream to determine whether there is any more data to be read.
148 hIsEOF :: Handle -> IO Bool
149 hIsEOF handle = wantReadableHandle_ "hIsEOF" handle $ \Handle__{..} -> do
151 cbuf <- readIORef haCharBuffer
152 if not (isEmptyBuffer cbuf) then return False else do
154 bbuf <- readIORef haByteBuffer
155 if not (isEmptyBuffer bbuf) then return False else do
157 -- NB. do no decoding, just fill the byte buffer; see #3808
158 (r,bbuf') <- Buffered.fillReadBuffer haDevice bbuf
161 else do writeIORef haByteBuffer bbuf'
164 -- ---------------------------------------------------------------------------
167 -- | Computation 'hLookAhead' returns the next character from the handle
168 -- without removing it from the input buffer, blocking until a character
171 -- This operation may fail with:
173 -- * 'isEOFError' if the end of file has been reached.
175 hLookAhead :: Handle -> IO Char
177 wantReadableHandle_ "hLookAhead" handle hLookAhead_
179 -- ---------------------------------------------------------------------------
180 -- Buffering Operations
182 -- Three kinds of buffering are supported: line-buffering,
183 -- block-buffering or no-buffering. See GHC.IO.Handle for definition and
184 -- further explanation of what the type represent.
186 -- | Computation 'hSetBuffering' @hdl mode@ sets the mode of buffering for
187 -- handle @hdl@ on subsequent reads and writes.
189 -- If the buffer mode is changed from 'BlockBuffering' or
190 -- 'LineBuffering' to 'NoBuffering', then
192 -- * if @hdl@ is writable, the buffer is flushed as for 'hFlush';
194 -- * if @hdl@ is not writable, the contents of the buffer is discarded.
196 -- This operation may fail with:
198 -- * 'isPermissionError' if the handle has already been used for reading
199 -- or writing and the implementation does not allow the buffering mode
202 hSetBuffering :: Handle -> BufferMode -> IO ()
203 hSetBuffering handle mode =
204 withAllHandles__ "hSetBuffering" handle $ \ handle_@Handle__{..} -> do
206 ClosedHandle -> ioe_closedHandle
208 if mode == haBufferMode then return handle_ else do
210 -- See [note Buffer Sizing] in GHC.IO.Handle.Types
214 BlockBuffering (Just n) | n <= 0 -> ioe_bufsiz n
217 -- for input terminals we need to put the terminal into
218 -- cooked or raw mode depending on the type of buffering.
219 is_tty <- IODevice.isTerminal haDevice
220 when (is_tty && isReadableHandleType haType) $
222 #ifndef mingw32_HOST_OS
223 -- 'raw' mode under win32 is a bit too specialised (and troublesome
224 -- for most common uses), so simply disable its use here.
225 NoBuffering -> IODevice.setRaw haDevice True
227 NoBuffering -> return ()
229 _ -> IODevice.setRaw haDevice False
231 -- throw away spare buffers, they might be the wrong size
232 writeIORef haBuffers BufferListNil
234 return Handle__{ haBufferMode = mode,.. }
236 -- -----------------------------------------------------------------------------
239 -- | The action 'hSetEncoding' @hdl@ @encoding@ changes the text encoding
240 -- for the handle @hdl@ to @encoding@. The default encoding when a 'Handle' is
241 -- created is 'localeEncoding', namely the default encoding for the current
244 -- To create a 'Handle' with no encoding at all, use 'openBinaryFile'. To
245 -- stop further encoding or decoding on an existing 'Handle', use
248 -- 'hSetEncoding' may need to flush buffered data in order to change
251 hSetEncoding :: Handle -> TextEncoding -> IO ()
252 hSetEncoding hdl encoding = do
253 withAllHandles__ "hSetEncoding" hdl $ \h_@Handle__{..} -> do
256 openTextEncoding (Just encoding) haType $ \ mb_encoder mb_decoder -> do
257 bbuf <- readIORef haByteBuffer
258 ref <- newIORef (error "last_decode")
259 return (Handle__{ haLastDecode = ref,
260 haDecoder = mb_decoder,
261 haEncoder = mb_encoder,
262 haCodec = Just encoding, .. })
264 -- | Return the current 'TextEncoding' for the specified 'Handle', or
265 -- 'Nothing' if the 'Handle' is in binary mode.
267 -- Note that the 'TextEncoding' remembers nothing about the state of
268 -- the encoder/decoder in use on this 'Handle'. For example, if the
269 -- encoding in use is UTF-16, then using 'hGetEncoding' and
270 -- 'hSetEncoding' to save and restore the encoding may result in an
271 -- extra byte-order-mark being written to the file.
273 hGetEncoding :: Handle -> IO (Maybe TextEncoding)
275 withHandle_ "hGetEncoding" hdl $ \h_@Handle__{..} -> return haCodec
277 -- -----------------------------------------------------------------------------
280 -- | The action 'hFlush' @hdl@ causes any items buffered for output
281 -- in handle @hdl@ to be sent immediately to the operating system.
283 -- This operation may fail with:
285 -- * 'isFullError' if the device is full;
287 -- * 'isPermissionError' if a system resource limit would be exceeded.
288 -- It is unspecified whether the characters in the buffer are discarded
289 -- or retained under these circumstances.
291 hFlush :: Handle -> IO ()
292 hFlush handle = wantWritableHandle "hFlush" handle flushWriteBuffer
294 -- | The action 'hFlushAll' @hdl@ flushes all buffered data in @hdl@,
295 -- including any buffered read data. Buffered read data is flushed
296 -- by seeking the file position back to the point before the bufferred
297 -- data was read, and hence only works if @hdl@ is seekable (see
300 -- This operation may fail with:
302 -- * 'isFullError' if the device is full;
304 -- * 'isPermissionError' if a system resource limit would be exceeded.
305 -- It is unspecified whether the characters in the buffer are discarded
306 -- or retained under these circumstances;
308 -- * 'isIllegalOperation' if @hdl@ has buffered read data, and is not
311 hFlushAll :: Handle -> IO ()
312 hFlushAll handle = withHandle_ "hFlushAll" handle flushBuffer
314 -- -----------------------------------------------------------------------------
315 -- Repositioning Handles
317 data HandlePosn = HandlePosn Handle HandlePosition
319 instance Eq HandlePosn where
320 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
322 instance Show HandlePosn where
323 showsPrec p (HandlePosn h pos) =
324 showsPrec p h . showString " at position " . shows pos
326 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
327 -- We represent it as an Integer on the Haskell side, but
328 -- cheat slightly in that hGetPosn calls upon a C helper
329 -- that reports the position back via (merely) an Int.
330 type HandlePosition = Integer
332 -- | Computation 'hGetPosn' @hdl@ returns the current I\/O position of
333 -- @hdl@ as a value of the abstract type 'HandlePosn'.
335 hGetPosn :: Handle -> IO HandlePosn
338 return (HandlePosn handle posn)
340 -- | If a call to 'hGetPosn' @hdl@ returns a position @p@,
341 -- then computation 'hSetPosn' @p@ sets the position of @hdl@
342 -- to the position it held at the time of the call to 'hGetPosn'.
344 -- This operation may fail with:
346 -- * 'isPermissionError' if a system resource limit would be exceeded.
348 hSetPosn :: HandlePosn -> IO ()
349 hSetPosn (HandlePosn h i) = hSeek h AbsoluteSeek i
351 -- ---------------------------------------------------------------------------
355 - when seeking using `SeekFromEnd', positive offsets (>=0) means
356 seeking at or past EOF.
358 - we possibly deviate from the report on the issue of seeking within
359 the buffer and whether to flush it or not. The report isn't exactly
363 -- | Computation 'hSeek' @hdl mode i@ sets the position of handle
364 -- @hdl@ depending on @mode@.
365 -- The offset @i@ is given in terms of 8-bit bytes.
367 -- If @hdl@ is block- or line-buffered, then seeking to a position which is not
368 -- in the current buffer will first cause any items in the output buffer to be
369 -- written to the device, and then cause the input buffer to be discarded.
370 -- Some handles may not be seekable (see 'hIsSeekable'), or only support a
371 -- subset of the possible positioning operations (for instance, it may only
372 -- be possible to seek to the end of a tape, or to a positive offset from
373 -- the beginning or current position).
374 -- It is not possible to set a negative I\/O position, or for
375 -- a physical file, an I\/O position beyond the current end-of-file.
377 -- This operation may fail with:
379 -- * 'isIllegalOperationError' if the Handle is not seekable, or does
380 -- not support the requested seek mode.
382 -- * 'isPermissionError' if a system resource limit would be exceeded.
384 hSeek :: Handle -> SeekMode -> Integer -> IO ()
385 hSeek handle mode offset =
386 wantSeekableHandle "hSeek" handle $ \ handle_@Handle__{..} -> do
387 debugIO ("hSeek " ++ show (mode,offset))
388 buf <- readIORef haCharBuffer
391 then do flushWriteBuffer handle_
392 IODevice.seek haDevice mode offset
395 let r = bufL buf; w = bufR buf
396 if mode == RelativeSeek && isNothing haDecoder &&
397 offset >= 0 && offset < fromIntegral (w - r)
398 then writeIORef haCharBuffer buf{ bufL = r + fromIntegral offset }
401 flushCharReadBuffer handle_
402 flushByteReadBuffer handle_
403 IODevice.seek haDevice mode offset
406 -- | Computation 'hTell' @hdl@ returns the current position of the
407 -- handle @hdl@, as the number of bytes from the beginning of
408 -- the file. The value returned may be subsequently passed to
409 -- 'hSeek' to reposition the handle to the current position.
411 -- This operation may fail with:
413 -- * 'isIllegalOperationError' if the Handle is not seekable.
415 hTell :: Handle -> IO Integer
417 wantSeekableHandle "hGetPosn" handle $ \ handle_@Handle__{..} -> do
419 posn <- IODevice.tell haDevice
421 -- we can't tell the real byte offset if there are buffered
422 -- Chars, so must flush first:
423 flushCharBuffer handle_
425 bbuf <- readIORef haByteBuffer
428 | isWriteBuffer bbuf = posn + fromIntegral (bufferElems bbuf)
429 | otherwise = posn - fromIntegral (bufferElems bbuf)
431 cbuf <- readIORef haCharBuffer
432 debugIO ("\nhGetPosn: (posn, real_posn) = " ++ show (posn, real_posn))
433 debugIO (" cbuf: " ++ summaryBuffer cbuf ++
434 " bbuf: " ++ summaryBuffer bbuf)
438 -- -----------------------------------------------------------------------------
441 -- A number of operations return information about the properties of a
442 -- handle. Each of these operations returns `True' if the handle has
443 -- the specified property, and `False' otherwise.
445 hIsOpen :: Handle -> IO Bool
447 withHandle_ "hIsOpen" handle $ \ handle_ -> do
448 case haType handle_ of
449 ClosedHandle -> return False
450 SemiClosedHandle -> return False
453 hIsClosed :: Handle -> IO Bool
455 withHandle_ "hIsClosed" handle $ \ handle_ -> do
456 case haType handle_ of
457 ClosedHandle -> return True
460 {- not defined, nor exported, but mentioned
461 here for documentation purposes:
463 hSemiClosed :: Handle -> IO Bool
467 return (not (ho || hc))
470 hIsReadable :: Handle -> IO Bool
471 hIsReadable (DuplexHandle _ _ _) = return True
473 withHandle_ "hIsReadable" handle $ \ handle_ -> do
474 case haType handle_ of
475 ClosedHandle -> ioe_closedHandle
476 SemiClosedHandle -> ioe_closedHandle
477 htype -> return (isReadableHandleType htype)
479 hIsWritable :: Handle -> IO Bool
480 hIsWritable (DuplexHandle _ _ _) = return True
482 withHandle_ "hIsWritable" handle $ \ handle_ -> do
483 case haType handle_ of
484 ClosedHandle -> ioe_closedHandle
485 SemiClosedHandle -> ioe_closedHandle
486 htype -> return (isWritableHandleType htype)
488 -- | Computation 'hGetBuffering' @hdl@ returns the current buffering mode
491 hGetBuffering :: Handle -> IO BufferMode
492 hGetBuffering handle =
493 withHandle_ "hGetBuffering" handle $ \ handle_ -> do
494 case haType handle_ of
495 ClosedHandle -> ioe_closedHandle
497 -- We're being non-standard here, and allow the buffering
498 -- of a semi-closed handle to be queried. -- sof 6/98
499 return (haBufferMode handle_) -- could be stricter..
501 hIsSeekable :: Handle -> IO Bool
503 withHandle_ "hIsSeekable" handle $ \ handle_@Handle__{..} -> do
505 ClosedHandle -> ioe_closedHandle
506 SemiClosedHandle -> ioe_closedHandle
507 AppendHandle -> return False
508 _ -> IODevice.isSeekable haDevice
510 -- -----------------------------------------------------------------------------
511 -- Changing echo status (Non-standard GHC extensions)
513 -- | Set the echoing status of a handle connected to a terminal.
515 hSetEcho :: Handle -> Bool -> IO ()
516 hSetEcho handle on = do
517 isT <- hIsTerminalDevice handle
521 withHandle_ "hSetEcho" handle $ \ Handle__{..} -> do
523 ClosedHandle -> ioe_closedHandle
524 _ -> IODevice.setEcho haDevice on
526 -- | Get the echoing status of a handle connected to a terminal.
528 hGetEcho :: Handle -> IO Bool
530 isT <- hIsTerminalDevice handle
534 withHandle_ "hGetEcho" handle $ \ Handle__{..} -> do
536 ClosedHandle -> ioe_closedHandle
537 _ -> IODevice.getEcho haDevice
539 -- | Is the handle connected to a terminal?
541 hIsTerminalDevice :: Handle -> IO Bool
542 hIsTerminalDevice handle = do
543 withHandle_ "hIsTerminalDevice" handle $ \ Handle__{..} -> do
545 ClosedHandle -> ioe_closedHandle
546 _ -> IODevice.isTerminal haDevice
548 -- -----------------------------------------------------------------------------
551 -- | Select binary mode ('True') or text mode ('False') on a open handle.
552 -- (See also 'openBinaryFile'.)
554 -- This has the same effect as calling 'hSetEncoding' with 'latin1', together
555 -- with 'hSetNewlineMode' with 'noNewlineTranslation'.
557 hSetBinaryMode :: Handle -> Bool -> IO ()
558 hSetBinaryMode handle bin =
559 withAllHandles__ "hSetBinaryMode" handle $ \ h_@Handle__{..} ->
564 let mb_te | bin = Nothing
565 | otherwise = Just localeEncoding
567 openTextEncoding mb_te haType $ \ mb_encoder mb_decoder -> do
569 -- should match the default newline mode, whatever that is
570 let nl | bin = noNewlineTranslation
571 | otherwise = nativeNewlineMode
573 bbuf <- readIORef haByteBuffer
574 ref <- newIORef (error "codec_state", bbuf)
576 return Handle__{ haLastDecode = ref,
577 haEncoder = mb_encoder,
578 haDecoder = mb_decoder,
580 haInputNL = inputNL nl,
581 haOutputNL = outputNL nl, .. }
583 -- -----------------------------------------------------------------------------
586 -- | Set the 'NewlineMode' on the specified 'Handle'. All buffered
587 -- data is flushed first.
588 hSetNewlineMode :: Handle -> NewlineMode -> IO ()
589 hSetNewlineMode handle NewlineMode{ inputNL=i, outputNL=o } =
590 withAllHandles__ "hSetNewlineMode" handle $ \h_@Handle__{..} ->
593 return h_{ haInputNL=i, haOutputNL=o }
595 -- -----------------------------------------------------------------------------
596 -- Duplicating a Handle
598 -- | Returns a duplicate of the original handle, with its own buffer.
599 -- The two Handles will share a file pointer, however. The original
600 -- handle's buffer is flushed, including discarding any input data,
601 -- before the handle is duplicated.
603 hDuplicate :: Handle -> IO Handle
604 hDuplicate h@(FileHandle path m) = do
605 withHandle_' "hDuplicate" h m $ \h_ ->
606 dupHandle path h Nothing h_ (Just handleFinalizer)
607 hDuplicate h@(DuplexHandle path r w) = do
608 write_side@(FileHandle _ write_m) <-
609 withHandle_' "hDuplicate" h w $ \h_ ->
610 dupHandle path h Nothing h_ (Just handleFinalizer)
611 read_side@(FileHandle _ read_m) <-
612 withHandle_' "hDuplicate" h r $ \h_ ->
613 dupHandle path h (Just write_m) h_ Nothing
614 return (DuplexHandle path read_m write_m)
616 dupHandle :: FilePath
618 -> Maybe (MVar Handle__)
620 -> Maybe HandleFinalizer
622 dupHandle filepath h other_side h_@Handle__{..} mb_finalizer = do
623 -- flush the buffer first, so we don't have to copy its contents
627 new_dev <- IODevice.dup haDevice
628 dupHandle_ new_dev filepath other_side h_ mb_finalizer
630 withHandle_' "dupHandle" h r $ \Handle__{haDevice=dev} -> do
631 dupHandle_ dev filepath other_side h_ mb_finalizer
633 dupHandle_ :: (IODevice dev, BufferedIO dev, Typeable dev) => dev
635 -> Maybe (MVar Handle__)
637 -> Maybe HandleFinalizer
639 dupHandle_ new_dev filepath other_side h_@Handle__{..} mb_finalizer = do
641 let mb_codec = if isJust haEncoder then Just localeEncoding else Nothing
642 mkHandle new_dev filepath haType True{-buffered-} mb_codec
643 NewlineMode { inputNL = haInputNL, outputNL = haOutputNL }
644 mb_finalizer other_side
646 -- -----------------------------------------------------------------------------
647 -- Replacing a Handle
650 Makes the second handle a duplicate of the first handle. The second
651 handle will be closed first, if it is not already.
653 This can be used to retarget the standard Handles, for example:
655 > do h <- openFile "mystdout" WriteMode
656 > hDuplicateTo h stdout
659 hDuplicateTo :: Handle -> Handle -> IO ()
660 hDuplicateTo h1@(FileHandle path m1) h2@(FileHandle _ m2) = do
661 withHandle__' "hDuplicateTo" h2 m2 $ \h2_ -> do
663 withHandle_' "hDuplicateTo" h1 m1 $ \h1_ -> do
664 dupHandleTo path h1 Nothing h2_ h1_ (Just handleFinalizer)
665 hDuplicateTo h1@(DuplexHandle path r1 w1) h2@(DuplexHandle _ r2 w2) = do
666 withHandle__' "hDuplicateTo" h2 w2 $ \w2_ -> do
668 withHandle_' "hDuplicateTo" h1 w1 $ \w1_ -> do
669 dupHandleTo path h1 Nothing w2_ w1_ (Just handleFinalizer)
670 withHandle__' "hDuplicateTo" h2 r2 $ \r2_ -> do
672 withHandle_' "hDuplicateTo" h1 r1 $ \r1_ -> do
673 dupHandleTo path h1 (Just w1) r2_ r1_ Nothing
675 ioe_dupHandlesNotCompatible h1
678 ioe_dupHandlesNotCompatible :: Handle -> IO a
679 ioe_dupHandlesNotCompatible h =
680 ioException (IOError (Just h) IllegalOperation "hDuplicateTo"
681 "handles are incompatible" Nothing Nothing)
683 dupHandleTo :: FilePath
685 -> Maybe (MVar Handle__)
688 -> Maybe HandleFinalizer
690 dupHandleTo filepath h other_side
691 hto_@Handle__{haDevice=devTo,..}
692 h_@Handle__{haDevice=dev} mb_finalizer = do
695 Nothing -> ioe_dupHandlesNotCompatible h
697 _ <- IODevice.dup2 dev dev'
698 FileHandle _ m <- dupHandle_ dev' filepath other_side h_ mb_finalizer
701 -- ---------------------------------------------------------------------------
704 -- | 'hShow' is in the 'IO' monad, and gives more comprehensive output
705 -- than the (pure) instance of 'Show' for 'Handle'.
707 hShow :: Handle -> IO String
708 hShow h@(FileHandle path _) = showHandle' path False h
709 hShow h@(DuplexHandle path _ _) = showHandle' path True h
711 showHandle' :: String -> Bool -> Handle -> IO String
712 showHandle' filepath is_duplex h =
713 withHandle_ "showHandle" h $ \hdl_ ->
715 showType | is_duplex = showString "duplex (read-write)"
716 | otherwise = shows (haType hdl_)
720 showHdl (haType hdl_)
721 (showString "loc=" . showString filepath . showChar ',' .
722 showString "type=" . showType . showChar ',' .
723 showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haCharBuffer hdl_))) (haBufferMode hdl_) . showString "}" )
727 showHdl :: HandleType -> ShowS -> ShowS
730 ClosedHandle -> shows ht . showString "}"
733 showBufMode :: Buffer e -> BufferMode -> ShowS
734 showBufMode buf bmo =
736 NoBuffering -> showString "none"
737 LineBuffering -> showString "line"
738 BlockBuffering (Just n) -> showString "block " . showParen True (shows n)
739 BlockBuffering Nothing -> showString "block " . showParen True (shows def)