+
+#if defined(__NHC__)
+-- Assume a unix platform, where text and binary I/O are identical.
+openBinaryFile = openFile
+hSetBinaryMode _ _ = return ()
+#endif
+
+-- $locking
+-- Implementations should enforce as far as possible, at least locally to the
+-- Haskell process, multiple-reader single-writer locking on files.
+-- That is, /there may either be many handles on the same file which manage
+-- input, or just one handle on the file which manages output/. If any
+-- open or semi-closed handle is managing a file for output, no new
+-- handle can be allocated for that file. If any open or semi-closed
+-- handle is managing a file for input, new handles can only be allocated
+-- if they do not manage output. Whether two files are the same is
+-- implementation-dependent, but they should normally be the same if they
+-- have the same absolute path name and neither has been renamed, for
+-- example.
+--
+-- /Warning/: the 'readFile' operation holds a semi-closed handle on
+-- the file until the entire contents of the file have been consumed.
+-- It follows that an attempt to write to a file (using 'writeFile', for
+-- example) that was earlier opened by 'readFile' will usually result in
+-- failure with 'System.IO.Error.isAlreadyInUseError'.
+
+-- -----------------------------------------------------------------------------
+-- Utils
+
+#ifdef __GLASGOW_HASKELL__
+-- Copied here to avoid recursive dependency with Control.Exception
+bracket
+ :: IO a -- ^ computation to run first (\"acquire resource\")
+ -> (a -> IO b) -- ^ computation to run last (\"release resource\")
+ -> (a -> IO c) -- ^ computation to run in-between
+ -> IO c -- returns the value from the in-between computation
+bracket before after thing =
+ block (do
+ a <- before
+ r <- catchException
+ (unblock (thing a))
+ (\e -> do { after a; throw e })
+ after a
+ return r
+ )