module IO (openFile) where
import DHandle (Handle(..))
import IOMode
import NHC.FFI
{- All this was incorrect. It opened a small gap between the
allocation of the ForeignObj, and its attachment into the program
graph with addrToFO. Hence occasionally, depending on exact
GC time, we got seg-faults.
-- foreign import openFileC :: CString -> Int -> IO Addr
-- #if !defined(TRACING)
-- foreign import "addrToHandle" addrToHandle :: Addr -> IO Handle
-- #else
-- foreign import "addrToHandle" addrToFO :: Addr -> IO ForeignObj
-- addrToHandle a = addrToFO a >>= return . Handle
-- #endif
-- openFile :: FilePath -> IOMode -> IO Handle
-- openFile fp iomode = do
-- a <- openFileC (toCString fp) (fromEnum iomode)
-- if a==nullAddr then do
-- errno <- getErrNo
-- throwIOError ("openFile "++show iomode) (Just fp) Nothing errno
-- else do
-- addrToHandle a
-- Note: the primitive openFileC returns an Addr that is in fact a
-- pointer to the C structure representing a ForeignObj. This is
-- how we can cast it to a Handle later on. The only reason we
-- don't return the Handle directly is so that we can test if it
-- is NULL (which can only be done in the Addr type), indicating a
-- failure to open the requested file.
-- Further note: the really correct way to do things would be to
-- return the Addr of the FILE* allocated by fopen(), then to
-- turn it into a ForeignObj by adding the finaliser closeFile.
-- Unfortunately, we haven't got finalisers of type IO () working yet,
-- so the finaliser has to be attached in the C world rather than
-- the Haskell world for the moment.
-}
foreign import ccall openFileC :: PackedString -> Int -> IO ForeignObj
openFile :: FilePath -> IOMode -> IO Handle
openFile fp iomode = do
fo <- openFileC (toCString fp) (fromEnum iomode)
if (foreignObjToAddr fo)==nullAddr then do
errno <- getErrNo
throwIOError ("openFile "++show iomode) (Just fp) Nothing errno
else return (Handle fo)
|