1 {-# OPTIONS_GHC -fno-implicit-prelude #-}
2 {-# OPTIONS_GHC -XRecordWildCards #-}
3 {-# OPTIONS_GHC -fno-warn-unused-matches #-}
4 -----------------------------------------------------------------------------
6 -- Module : GHC.IO.Handle
7 -- Copyright : (c) The University of Glasgow, 1994-2009
8 -- License : see libraries/base/LICENSE
10 -- Maintainer : libraries@haskell.org
11 -- Stability : provisional
12 -- Portability : non-portable
14 -- External API for GHC's Handle implementation
16 -----------------------------------------------------------------------------
18 module GHC.IO.Handle (
22 mkFileHandle, mkDuplexHandle,
24 hFileSize, hSetFileSize, hIsEOF, hLookAhead,
25 hSetBuffering, hSetBinaryMode, hSetEncoding,
26 hFlush, hFlushAll, hDuplicate, hDuplicateTo,
30 HandlePosition, HandlePosn(..), hGetPosn, hSetPosn,
31 SeekMode(..), hSeek, hTell,
33 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,
34 hSetEcho, hGetEcho, hIsTerminalDevice,
36 hSetNewlineMode, Newline(..), NewlineMode(..), nativeNewline,
37 noNewlineTranslation, universalNewlineMode, nativeNewlineMode,
41 hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,
43 hGetBuf, hGetBufNonBlocking, hPutBuf, hPutBufNonBlocking
47 import GHC.IO.Exception
48 import GHC.IO.Encoding
50 import GHC.IO.BufferedIO ( BufferedIO )
51 import GHC.IO.Device as IODevice
52 import GHC.IO.Handle.Types
53 import GHC.IO.Handle.Internals
54 import GHC.IO.Handle.Text
55 import System.IO.Error
68 -- ---------------------------------------------------------------------------
71 -- | Computation 'hClose' @hdl@ makes handle @hdl@ closed. Before the
72 -- computation finishes, if @hdl@ is writable its buffer is flushed as
74 -- Performing 'hClose' on a handle that has already been closed has no effect;
75 -- doing so is not an error. All other operations on a closed handle will fail.
76 -- If 'hClose' fails for any reason, any further operations (apart from
77 -- 'hClose') on the handle will still fail as if @hdl@ had been successfully
80 hClose :: Handle -> IO ()
81 hClose h@(FileHandle _ m) = do
83 hClose_maybethrow mb_exc h
84 hClose h@(DuplexHandle _ r w) = do
85 mb_exc1 <- hClose' h w
86 mb_exc2 <- hClose' h r
89 Just e -> hClose_maybethrow mb_exc2 h
91 hClose_maybethrow :: Maybe SomeException -> Handle -> IO ()
92 hClose_maybethrow Nothing h = return ()
93 hClose_maybethrow (Just e) h = hClose_rethrow e h
95 hClose_rethrow :: SomeException -> Handle -> IO ()
97 case fromException e of
98 Just ioe -> ioError (augmentIOError ioe "hClose" h)
101 hClose' :: Handle -> MVar Handle__ -> IO (Maybe SomeException)
102 hClose' h m = withHandle' "hClose" h m $ hClose_help
104 -----------------------------------------------------------------------------
105 -- Detecting and changing the size of a file
107 -- | For a handle @hdl@ which attached to a physical file,
108 -- 'hFileSize' @hdl@ returns the size of that file in 8-bit bytes.
110 hFileSize :: Handle -> IO Integer
112 withHandle_ "hFileSize" handle $ \ handle_@Handle__{haDevice=dev} -> do
113 case haType handle_ of
114 ClosedHandle -> ioe_closedHandle
115 SemiClosedHandle -> ioe_closedHandle
116 _ -> do flushWriteBuffer handle_
117 r <- IODevice.getSize dev
120 else ioException (IOError Nothing InappropriateType "hFileSize"
121 "not a regular file" Nothing Nothing)
124 -- | 'hSetFileSize' @hdl@ @size@ truncates the physical file with handle @hdl@ to @size@ bytes.
126 hSetFileSize :: Handle -> Integer -> IO ()
127 hSetFileSize handle size =
128 withHandle_ "hSetFileSize" handle $ \ handle_@Handle__{haDevice=dev} -> do
129 case haType handle_ of
130 ClosedHandle -> ioe_closedHandle
131 SemiClosedHandle -> ioe_closedHandle
132 _ -> do flushWriteBuffer handle_
133 IODevice.setSize dev size
136 -- ---------------------------------------------------------------------------
137 -- Detecting the End of Input
139 -- | For a readable handle @hdl@, 'hIsEOF' @hdl@ returns
140 -- 'True' if no further input can be taken from @hdl@ or for a
141 -- physical file, if the current I\/O position is equal to the length of
142 -- the file. Otherwise, it returns 'False'.
144 -- NOTE: 'hIsEOF' may block, because it is the same as calling
145 -- 'hLookAhead' and checking for an EOF exception.
147 hIsEOF :: Handle -> IO Bool
150 (do hLookAhead handle; return False)
151 (\e -> if isEOFError e then return True else ioError e)
153 -- ---------------------------------------------------------------------------
156 -- | Computation 'hLookAhead' returns the next character from the handle
157 -- without removing it from the input buffer, blocking until a character
160 -- This operation may fail with:
162 -- * 'isEOFError' if the end of file has been reached.
164 hLookAhead :: Handle -> IO Char
166 wantReadableHandle_ "hLookAhead" handle hLookAhead_
168 -- ---------------------------------------------------------------------------
169 -- Buffering Operations
171 -- Three kinds of buffering are supported: line-buffering,
172 -- block-buffering or no-buffering. See GHC.IO.Handle for definition and
173 -- further explanation of what the type represent.
175 -- | Computation 'hSetBuffering' @hdl mode@ sets the mode of buffering for
176 -- handle @hdl@ on subsequent reads and writes.
178 -- If the buffer mode is changed from 'BlockBuffering' or
179 -- 'LineBuffering' to 'NoBuffering', then
181 -- * if @hdl@ is writable, the buffer is flushed as for 'hFlush';
183 -- * if @hdl@ is not writable, the contents of the buffer is discarded.
185 -- This operation may fail with:
187 -- * 'isPermissionError' if the handle has already been used for reading
188 -- or writing and the implementation does not allow the buffering mode
191 hSetBuffering :: Handle -> BufferMode -> IO ()
192 hSetBuffering handle mode =
193 withAllHandles__ "hSetBuffering" handle $ \ handle_@Handle__{..} -> do
195 ClosedHandle -> ioe_closedHandle
197 if mode == haBufferMode then return handle_ else do
200 - we flush the old buffer regardless of whether
201 the new buffer could fit the contents of the old buffer
203 - allow a handle's buffering to change even if IO has
204 occurred (ANSI C spec. does not allow this, nor did
205 the previous implementation of IO.hSetBuffering).
206 - a non-standard extension is to allow the buffering
207 of semi-closed handles to change [sof 6/98]
209 flushCharBuffer handle_
211 let state = initBufferState haType
212 reading = not (isWritableHandleType haType)
216 -- See [note Buffer Sizing], GHC.IO.Handle.Types
217 NoBuffering | reading -> newCharBuffer dEFAULT_CHAR_BUFFER_SIZE state
218 | otherwise -> newCharBuffer 1 state
219 LineBuffering -> newCharBuffer dEFAULT_CHAR_BUFFER_SIZE state
220 BlockBuffering Nothing -> newCharBuffer dEFAULT_CHAR_BUFFER_SIZE state
221 BlockBuffering (Just n) | n <= 0 -> ioe_bufsiz n
222 | otherwise -> newCharBuffer n state
224 writeIORef haCharBuffer new_buf
226 -- for input terminals we need to put the terminal into
227 -- cooked or raw mode depending on the type of buffering.
228 is_tty <- IODevice.isTerminal haDevice
229 when (is_tty && isReadableHandleType haType) $
231 #ifndef mingw32_HOST_OS
232 -- 'raw' mode under win32 is a bit too specialised (and troublesome
233 -- for most common uses), so simply disable its use here.
234 NoBuffering -> IODevice.setRaw haDevice True
236 NoBuffering -> return ()
238 _ -> IODevice.setRaw haDevice False
240 -- throw away spare buffers, they might be the wrong size
241 writeIORef haBuffers BufferListNil
243 return Handle__{ haBufferMode = mode,.. }
245 -- -----------------------------------------------------------------------------
248 -- | The action 'hSetEncoding' @hdl@ @encoding@ changes the text encoding
249 -- for the handle @hdl@ to @encoding@. Encodings are available from the
250 -- module "GHC.IO.Encoding". The default encoding when a 'Handle' is
251 -- created is 'localeEncoding', namely the default encoding for the current
254 -- To create a 'Handle' with no encoding at all, use 'openBinaryFile'. To
255 -- stop further encoding or decoding on an existing 'Handle', use
258 hSetEncoding :: Handle -> TextEncoding -> IO ()
259 hSetEncoding hdl encoding = do
260 withHandle "hSetEncoding" hdl $ \h_@Handle__{..} -> do
262 openTextEncoding (Just encoding) haType $ \ mb_encoder mb_decoder -> do
263 bbuf <- readIORef haByteBuffer
264 ref <- newIORef (error "last_decode")
265 return (Handle__{ haLastDecode = ref, haDecoder = mb_decoder, haEncoder = mb_encoder, .. },
268 -- -----------------------------------------------------------------------------
271 -- | The action 'hFlush' @hdl@ causes any items buffered for output
272 -- in handle @hdl@ to be sent immediately to the operating system.
274 -- This operation may fail with:
276 -- * 'isFullError' if the device is full;
278 -- * 'isPermissionError' if a system resource limit would be exceeded.
279 -- It is unspecified whether the characters in the buffer are discarded
280 -- or retained under these circumstances.
282 hFlush :: Handle -> IO ()
283 hFlush handle = wantWritableHandle "hFlush" handle flushWriteBuffer
285 -- | The action 'hFlushAll' @hdl@ flushes all buffered data in @hdl@,
286 -- including any buffered read data. Buffered read data is flushed
287 -- by seeking the file position back to the point before the bufferred
288 -- data was read, and hence only works if @hdl@ is seekable (see
291 -- This operation may fail with:
293 -- * 'isFullError' if the device is full;
295 -- * 'isPermissionError' if a system resource limit would be exceeded.
296 -- It is unspecified whether the characters in the buffer are discarded
297 -- or retained under these circumstances;
299 -- * 'isIllegalOperation' if @hdl@ has buffered read data, and is not
302 hFlushAll :: Handle -> IO ()
303 hFlushAll handle = withHandle_ "hFlushAll" handle flushBuffer
305 -- -----------------------------------------------------------------------------
306 -- Repositioning Handles
308 data HandlePosn = HandlePosn Handle HandlePosition
310 instance Eq HandlePosn where
311 (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
313 instance Show HandlePosn where
314 showsPrec p (HandlePosn h pos) =
315 showsPrec p h . showString " at position " . shows pos
317 -- HandlePosition is the Haskell equivalent of POSIX' off_t.
318 -- We represent it as an Integer on the Haskell side, but
319 -- cheat slightly in that hGetPosn calls upon a C helper
320 -- that reports the position back via (merely) an Int.
321 type HandlePosition = Integer
323 -- | Computation 'hGetPosn' @hdl@ returns the current I\/O position of
324 -- @hdl@ as a value of the abstract type 'HandlePosn'.
326 hGetPosn :: Handle -> IO HandlePosn
329 return (HandlePosn handle posn)
331 -- | If a call to 'hGetPosn' @hdl@ returns a position @p@,
332 -- then computation 'hSetPosn' @p@ sets the position of @hdl@
333 -- to the position it held at the time of the call to 'hGetPosn'.
335 -- This operation may fail with:
337 -- * 'isPermissionError' if a system resource limit would be exceeded.
339 hSetPosn :: HandlePosn -> IO ()
340 hSetPosn (HandlePosn h i) = hSeek h AbsoluteSeek i
342 -- ---------------------------------------------------------------------------
346 - when seeking using `SeekFromEnd', positive offsets (>=0) means
347 seeking at or past EOF.
349 - we possibly deviate from the report on the issue of seeking within
350 the buffer and whether to flush it or not. The report isn't exactly
354 -- | Computation 'hSeek' @hdl mode i@ sets the position of handle
355 -- @hdl@ depending on @mode@.
356 -- The offset @i@ is given in terms of 8-bit bytes.
358 -- If @hdl@ is block- or line-buffered, then seeking to a position which is not
359 -- in the current buffer will first cause any items in the output buffer to be
360 -- written to the device, and then cause the input buffer to be discarded.
361 -- Some handles may not be seekable (see 'hIsSeekable'), or only support a
362 -- subset of the possible positioning operations (for instance, it may only
363 -- be possible to seek to the end of a tape, or to a positive offset from
364 -- the beginning or current position).
365 -- It is not possible to set a negative I\/O position, or for
366 -- a physical file, an I\/O position beyond the current end-of-file.
368 -- This operation may fail with:
370 -- * 'isPermissionError' if a system resource limit would be exceeded.
372 hSeek :: Handle -> SeekMode -> Integer -> IO ()
373 hSeek handle mode offset =
374 wantSeekableHandle "hSeek" handle $ \ handle_@Handle__{..} -> do
375 debugIO ("hSeek " ++ show (mode,offset))
376 buf <- readIORef haCharBuffer
379 then do flushWriteBuffer handle_
380 IODevice.seek haDevice mode offset
383 let r = bufL buf; w = bufR buf
384 if mode == RelativeSeek && isNothing haDecoder &&
385 offset >= 0 && offset < fromIntegral (w - r)
386 then writeIORef haCharBuffer buf{ bufL = r + fromIntegral offset }
389 flushCharReadBuffer handle_
390 flushByteReadBuffer handle_
391 IODevice.seek haDevice mode offset
394 hTell :: Handle -> IO Integer
396 wantSeekableHandle "hGetPosn" handle $ \ handle_@Handle__{..} -> do
398 posn <- IODevice.tell haDevice
400 cbuf <- readIORef haCharBuffer
401 bbuf <- readIORef haByteBuffer
404 | isWriteBuffer cbuf = posn + fromIntegral (bufR cbuf)
405 | otherwise = posn - fromIntegral (bufR cbuf - bufL cbuf)
406 - fromIntegral (bufR bbuf - bufL bbuf)
408 debugIO ("\nhGetPosn: (posn, real_posn) = " ++ show (posn, real_posn))
409 debugIO (" cbuf: " ++ summaryBuffer cbuf ++
410 " bbuf: " ++ summaryBuffer bbuf)
414 -- -----------------------------------------------------------------------------
417 -- A number of operations return information about the properties of a
418 -- handle. Each of these operations returns `True' if the handle has
419 -- the specified property, and `False' otherwise.
421 hIsOpen :: Handle -> IO Bool
423 withHandle_ "hIsOpen" handle $ \ handle_ -> do
424 case haType handle_ of
425 ClosedHandle -> return False
426 SemiClosedHandle -> return False
429 hIsClosed :: Handle -> IO Bool
431 withHandle_ "hIsClosed" handle $ \ handle_ -> do
432 case haType handle_ of
433 ClosedHandle -> return True
436 {- not defined, nor exported, but mentioned
437 here for documentation purposes:
439 hSemiClosed :: Handle -> IO Bool
443 return (not (ho || hc))
446 hIsReadable :: Handle -> IO Bool
447 hIsReadable (DuplexHandle _ _ _) = return True
449 withHandle_ "hIsReadable" handle $ \ handle_ -> do
450 case haType handle_ of
451 ClosedHandle -> ioe_closedHandle
452 SemiClosedHandle -> ioe_closedHandle
453 htype -> return (isReadableHandleType htype)
455 hIsWritable :: Handle -> IO Bool
456 hIsWritable (DuplexHandle _ _ _) = return True
458 withHandle_ "hIsWritable" handle $ \ handle_ -> do
459 case haType handle_ of
460 ClosedHandle -> ioe_closedHandle
461 SemiClosedHandle -> ioe_closedHandle
462 htype -> return (isWritableHandleType htype)
464 -- | Computation 'hGetBuffering' @hdl@ returns the current buffering mode
467 hGetBuffering :: Handle -> IO BufferMode
468 hGetBuffering handle =
469 withHandle_ "hGetBuffering" handle $ \ handle_ -> do
470 case haType handle_ of
471 ClosedHandle -> ioe_closedHandle
473 -- We're being non-standard here, and allow the buffering
474 -- of a semi-closed handle to be queried. -- sof 6/98
475 return (haBufferMode handle_) -- could be stricter..
477 hIsSeekable :: Handle -> IO Bool
479 withHandle_ "hIsSeekable" handle $ \ handle_@Handle__{..} -> do
481 ClosedHandle -> ioe_closedHandle
482 SemiClosedHandle -> ioe_closedHandle
483 AppendHandle -> return False
484 _ -> IODevice.isSeekable haDevice
486 -- -----------------------------------------------------------------------------
487 -- Changing echo status (Non-standard GHC extensions)
489 -- | Set the echoing status of a handle connected to a terminal.
491 hSetEcho :: Handle -> Bool -> IO ()
492 hSetEcho handle on = do
493 isT <- hIsTerminalDevice handle
497 withHandle_ "hSetEcho" handle $ \ Handle__{..} -> do
499 ClosedHandle -> ioe_closedHandle
500 _ -> IODevice.setEcho haDevice on
502 -- | Get the echoing status of a handle connected to a terminal.
504 hGetEcho :: Handle -> IO Bool
506 isT <- hIsTerminalDevice handle
510 withHandle_ "hGetEcho" handle $ \ Handle__{..} -> do
512 ClosedHandle -> ioe_closedHandle
513 _ -> IODevice.getEcho haDevice
515 -- | Is the handle connected to a terminal?
517 hIsTerminalDevice :: Handle -> IO Bool
518 hIsTerminalDevice handle = do
519 withHandle_ "hIsTerminalDevice" handle $ \ Handle__{..} -> do
521 ClosedHandle -> ioe_closedHandle
522 _ -> IODevice.isTerminal haDevice
524 -- -----------------------------------------------------------------------------
527 -- | Select binary mode ('True') or text mode ('False') on a open handle.
528 -- (See also 'openBinaryFile'.)
530 -- This has the same effect as calling 'hSetEncoding' with 'latin1', together
531 -- with 'hSetNewlineMode' with 'noNewlineTranslation'.
533 hSetBinaryMode :: Handle -> Bool -> IO ()
534 hSetBinaryMode handle bin =
535 withAllHandles__ "hSetBinaryMode" handle $ \ h_@Handle__{..} ->
539 let mb_te | bin = Nothing
540 | otherwise = Just localeEncoding
542 openTextEncoding mb_te haType $ \ mb_encoder mb_decoder -> do
544 -- should match the default newline mode, whatever that is
545 let nl | bin = noNewlineTranslation
546 | otherwise = nativeNewlineMode
548 bbuf <- readIORef haByteBuffer
549 ref <- newIORef (error "codec_state", bbuf)
551 return Handle__{ haLastDecode = ref,
552 haEncoder = mb_encoder,
553 haDecoder = mb_decoder,
554 haInputNL = inputNL nl,
555 haOutputNL = outputNL nl, .. }
557 -- -----------------------------------------------------------------------------
560 -- | Set the 'NewlineMode' on the specified 'Handle'. All buffered
561 -- data is flushed first.
562 hSetNewlineMode :: Handle -> NewlineMode -> IO ()
563 hSetNewlineMode handle NewlineMode{ inputNL=i, outputNL=o } =
564 withAllHandles__ "hSetNewlineMode" handle $ \h_@Handle__{..} ->
567 return h_{ haInputNL=i, haOutputNL=o }
569 -- -----------------------------------------------------------------------------
570 -- Duplicating a Handle
572 -- | Returns a duplicate of the original handle, with its own buffer.
573 -- The two Handles will share a file pointer, however. The original
574 -- handle's buffer is flushed, including discarding any input data,
575 -- before the handle is duplicated.
577 hDuplicate :: Handle -> IO Handle
578 hDuplicate h@(FileHandle path m) = do
579 withHandle_' "hDuplicate" h m $ \h_ ->
580 dupHandle path h Nothing h_ (Just handleFinalizer)
581 hDuplicate h@(DuplexHandle path r w) = do
582 write_side@(FileHandle _ write_m) <-
583 withHandle_' "hDuplicate" h w $ \h_ ->
584 dupHandle path h Nothing h_ (Just handleFinalizer)
585 read_side@(FileHandle _ read_m) <-
586 withHandle_' "hDuplicate" h r $ \h_ ->
587 dupHandle path h (Just write_m) h_ Nothing
588 return (DuplexHandle path read_m write_m)
590 dupHandle :: FilePath
592 -> Maybe (MVar Handle__)
594 -> Maybe HandleFinalizer
596 dupHandle filepath h other_side h_@Handle__{..} mb_finalizer = do
597 -- flush the buffer first, so we don't have to copy its contents
601 new_dev <- IODevice.dup haDevice
602 dupHandle_ new_dev filepath other_side h_ mb_finalizer
604 withHandle_' "dupHandle" h r $ \Handle__{haDevice=dev} -> do
605 dupHandle_ dev filepath other_side h_ mb_finalizer
607 dupHandle_ :: (IODevice dev, BufferedIO dev, Typeable dev) => dev
609 -> Maybe (MVar Handle__)
611 -> Maybe HandleFinalizer
613 dupHandle_ new_dev filepath other_side h_@Handle__{..} mb_finalizer = do
615 let mb_codec = if isJust haEncoder then Just localeEncoding else Nothing
616 mkHandle new_dev filepath haType True{-buffered-} mb_codec
617 NewlineMode { inputNL = haInputNL, outputNL = haOutputNL }
618 mb_finalizer other_side
620 -- -----------------------------------------------------------------------------
621 -- Replacing a Handle
624 Makes the second handle a duplicate of the first handle. The second
625 handle will be closed first, if it is not already.
627 This can be used to retarget the standard Handles, for example:
629 > do h <- openFile "mystdout" WriteMode
630 > hDuplicateTo h stdout
633 hDuplicateTo :: Handle -> Handle -> IO ()
634 hDuplicateTo h1@(FileHandle path m1) h2@(FileHandle _ m2) = do
635 withHandle__' "hDuplicateTo" h2 m2 $ \h2_ -> do
637 withHandle_' "hDuplicateTo" h1 m1 $ \h1_ -> do
638 dupHandleTo path h1 Nothing h2_ h1_ (Just handleFinalizer)
639 hDuplicateTo h1@(DuplexHandle path r1 w1) h2@(DuplexHandle _ r2 w2) = do
640 withHandle__' "hDuplicateTo" h2 w2 $ \w2_ -> do
642 withHandle_' "hDuplicateTo" h1 w1 $ \w1_ -> do
643 dupHandleTo path h1 Nothing w2_ w1_ (Just handleFinalizer)
644 withHandle__' "hDuplicateTo" h2 r2 $ \r2_ -> do
646 withHandle_' "hDuplicateTo" h1 r1 $ \r1_ -> do
647 dupHandleTo path h1 (Just w1) r2_ r1_ Nothing
649 ioe_dupHandlesNotCompatible h1
652 ioe_dupHandlesNotCompatible :: Handle -> IO a
653 ioe_dupHandlesNotCompatible h =
654 ioException (IOError (Just h) IllegalOperation "hDuplicateTo"
655 "handles are incompatible" Nothing Nothing)
657 dupHandleTo :: FilePath
659 -> Maybe (MVar Handle__)
662 -> Maybe HandleFinalizer
664 dupHandleTo filepath h other_side
665 hto_@Handle__{haDevice=devTo,..}
666 h_@Handle__{haDevice=dev} mb_finalizer = do
669 Nothing -> ioe_dupHandlesNotCompatible h
671 IODevice.dup2 dev dev'
672 FileHandle _ m <- dupHandle_ dev' filepath other_side h_ mb_finalizer
675 -- ---------------------------------------------------------------------------
678 -- | 'hShow' is in the 'IO' monad, and gives more comprehensive output
679 -- than the (pure) instance of 'Show' for 'Handle'.
681 hShow :: Handle -> IO String
682 hShow h@(FileHandle path _) = showHandle' path False h
683 hShow h@(DuplexHandle path _ _) = showHandle' path True h
685 showHandle' :: String -> Bool -> Handle -> IO String
686 showHandle' filepath is_duplex h =
687 withHandle_ "showHandle" h $ \hdl_ ->
689 showType | is_duplex = showString "duplex (read-write)"
690 | otherwise = shows (haType hdl_)
694 showHdl (haType hdl_)
695 (showString "loc=" . showString filepath . showChar ',' .
696 showString "type=" . showType . showChar ',' .
697 showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haCharBuffer hdl_))) (haBufferMode hdl_) . showString "}" )
701 showHdl :: HandleType -> ShowS -> ShowS
704 ClosedHandle -> shows ht . showString "}"
707 showBufMode :: Buffer e -> BufferMode -> ShowS
708 showBufMode buf bmo =
710 NoBuffering -> showString "none"
711 LineBuffering -> showString "line"
712 BlockBuffering (Just n) -> showString "block " . showParen True (shows n)
713 BlockBuffering Nothing -> showString "block " . showParen True (shows def)