content: module System.IO.Open(
    stdin, stdout, stderr,
    openFileM,
    openBinaryFileM,
    ) where
  import qualified Prelude()              -- do not import Prelude
  import Primitives(ForeignPtr, IO)
  import Control.Monad
  import Data.Char
  import Data.Function
  import Data.Functor
  import Data.Maybe
  import Foreign.C.String
  import Foreign.Ptr
  import Mhs.Builtin
  import System.IO.Internal
  
  -- Functions returning Handles
  -- These can be based on FILE or file descriptors.
  
  primStdin        :: ForeignPtr BFILE
  primStdin         = _primitive "IO.stdin"
  primStdout       :: ForeignPtr BFILE
  primStdout        = _primitive "IO.stdout"
  primStderr       :: ForeignPtr BFILE
  primStderr        = _primitive "IO.stderr"
  
  data FILE
  
  -- FILE stuff
  foreign import ccall "fopen"        c_fopen        :: CString -> CString -> IO (Ptr FILE)
  foreign import ccall "add_FILE"     c_add_FILE     :: Ptr FILE           -> IO (Ptr BFILE)
  foreign import ccall "add_utf8"     c_add_utf8     :: Ptr BFILE          -> IO (Ptr BFILE)
  
  stdin  :: Handle
  stdin  = unsafeHandle primStdin  HRead  "stdin"
  stdout :: Handle
  stdout = unsafeHandle primStdout HWrite "stdout"
  stderr :: Handle
  stderr = unsafeHandle primStderr HWrite "stderr"
  
  openFILEM :: FilePath -> IOMode -> IO (Maybe (Ptr FILE))
  openFILEM p m = do
    let
      ms = case m of
            ReadMode -> "r"
            WriteMode -> "w"
            AppendMode -> "a"
            ReadWriteMode -> "w+"
    h <- withCAString p $ \cp -> withCAString ms $ \ cm -> c_fopen cp cm
    if h == nullPtr then
      return Nothing
     else
      return (Just h)
  
  openFileM :: FilePath -> IOMode -> IO (Maybe Handle)
  openFileM fn m = do
    mf <- openFILEM fn m
    case mf of
      Nothing -> return Nothing
      Just p -> do { q <- c_add_utf8 =<< c_add_FILE p; Just <$> mkHandle fn q (ioModeToHMode m) }
  
  openBinaryFileM :: String -> IOMode -> IO (Maybe Handle)
  openBinaryFileM fn m = do
    mf <- openFILEM fn m
    case mf of
      Nothing -> return Nothing
      Just p -> do { q <- c_add_FILE p; Just <$> mkHandle fn q (ioModeToHMode m) }
  