summaryrefslogtreecommitdiff
path: root/ghc/lib/exts
diff options
context:
space:
mode:
authorsof <unknown>1999-09-11 18:30:49 +0000
committersof <unknown>1999-09-11 18:30:49 +0000
commit55e738bfcffff4b7d01857ec2dfb727069ffe505 (patch)
treef8457ecfc0a2056f8ac74723ac536474cac075cf /ghc/lib/exts
parente982571c11551ba3513582a85e3bbe617b1bb649 (diff)
downloadhaskell-55e738bfcffff4b7d01857ec2dfb727069ffe505.tar.gz
[project @ 1999-09-11 18:30:49 by sof]
Experimental support for re-routeing I/O on a Handle to that of another for the duration of an IO action. Used to provide the following three (exported) actions withStdin, withStdout, withStderr :: Handle -> IO a -> IO a which 'replaces' one of the standard handles with that of the supplied handle while performing the second action.
Diffstat (limited to 'ghc/lib/exts')
-rw-r--r--ghc/lib/exts/IOExts.lhs55
1 files changed, 55 insertions, 0 deletions
diff --git a/ghc/lib/exts/IOExts.lhs b/ghc/lib/exts/IOExts.lhs
index b973fa6fa0..e83a78fd69 100644
--- a/ghc/lib/exts/IOExts.lhs
+++ b/ghc/lib/exts/IOExts.lhs
@@ -46,6 +46,10 @@ module IOExts
, hGetEcho
, hIsTerminalDevice
, hConnectTo
+ , withHandleFor
+ , withStdout
+ , withStdin
+ , withStderr
#endif
, trace
#ifdef __HUGS__
@@ -68,6 +72,7 @@ import ST
#else
import PrelBase
import PrelIOBase
+import IO
import PrelHandle ( openFileEx, IOModeEx(..),
hSetEcho, hGetEcho, getHandleFd
)
@@ -209,3 +214,53 @@ foreign import ccall "freeHaskellFunctionPtr"
\end{code}
+(Experimental)
+
+Support for redirecting I/O on a handle to another for the
+duration of an IO action. To re-route a handle, it is first
+flushed, followed by replacing its innards (i.e., FILE_OBJECT)
+with that of the other. This happens before and after the
+action is executed.
+
+If the action raises an exception, the handle is replaced back
+to its old contents, but without flushing it first - as this
+may provoke exceptions. Notice that the action may perform
+I/O on either Handle, with the result that the I/O is interleaved.
+(Why you would want to do this, is a completely different matter.)
+
+ToDo: probably want to restrict what kind of handles can be
+replaced with another - i.e., don't want to be able to replace
+a writeable handle with a readable one.
+
+\begin{code}
+withHandleFor :: Handle
+ -> Handle
+ -> IO a
+ -> IO a
+withHandleFor h1 h2 act = do
+ h1_fo <- getFO h1
+ plugIn h1_fo
+ where
+ plugIn h1_fo = do
+ hFlush h2
+ h2_fo <- withHandle h2 $ \ h2_ -> return (h2_{haFO__=h1_fo}, haFO__ h2_)
+ catch (act >>= \ x -> hFlush h2 >> setFO h2 h2_fo >> return x)
+ (\ err -> setFO h2 h2_fo >> ioError err)
+
+ setFO h fo =
+ withHandle h $ \ h_ -> return (h_{haFO__=fo}, ())
+
+ getFO h =
+ wantRWHandle "withHandleFor" h $ \ h_ ->
+ return (haFO__ h_)
+
+\end{code}
+
+Derived @withHandleFor@ combinators and, at the moment, these
+are exported from @IOExts@ and not @withHandleFor@ itself.
+
+\begin{code}
+withStdin h a = withHandleFor h stdin a
+withStdout h a = withHandleFor h stdout a
+withStderr h a = withHandleFor h stderr a
+\end{code}