{-# LANGUAGE ImpredicativeTypes #-} module Ho.Binary(readHoFile,recordHoFile,readHlFile,recordHlFile) where import Codec.Compression.Zlib import Control.Monad import Data.Binary import System.Directory import Text.Printf import Util.Gen import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import qualified Data.Version import FrontEnd.Rename(FieldMap(..)) import Ho.Type import Name.Binary() import Options import Support.CFF import Support.MapBinaryInstance import Support.CompatMingw32 current_version :: Int current_version = 11 readHFile :: FilePath -> IO (FilePath,HoHeader,forall a . Binary a => ChunkType -> a) readHFile fn = do bs <- BS.readFile fn fn' <- shortenPath fn (ct,mp) <- bsCFF bs True <- return $ ct == cff_magic let fc ct = case lookup ct mp of Nothing -> error $ "No chunk '" ++ show ct ++ "' found in file " ++ fn Just x -> decode . decompress $ LBS.fromChunks [x] let hoh = fc cff_jhdr when (hohVersion hoh /= current_version) $ fail "invalid version in hofile" return (fn',hoh,fc) readHoFile :: FilePath -> IO (HoHeader,HoIDeps,Ho) readHoFile fn = do (_fn,hoh,fc) <- readHFile fn let Left modGroup = hohName hoh return (hoh,fc cff_idep,Ho { hoModuleGroup = modGroup, hoTcInfo = fc cff_defs, hoBuild = fc cff_core}) recordHoFile :: Ho -- ^ File to record -> HoIDeps -> [FilePath] -- ^ files to write to -> HoHeader -- ^ file header -> IO () recordHoFile ho idep fs header = do if optNoWriteHo options then do when verbose $ do fs' <- mapM shortenPath fs putErrLn $ "Skipping Writing Ho Files: " ++ show fs' else do let removeLink' fn = iocatch (removeFile fn) (\_ -> return ()) let g (fn:fs) = do f fn mapM_ (l fn) fs return () g [] = error "Ho.g: shouldn't happen" l fn fn' = do when verbose $ do fn_ <- shortenPath fn fn_' <- shortenPath fn' when (optNoWriteHo options) $ putErr "Skipping " putErrLn $ printf "Linking haskell object file: %s to %s" fn_' fn_ if optNoWriteHo options then return () else do let tfn = fn' ++ ".tmp" removeLink' tfn createLinkCompat fn tfn renameFile tfn fn' f fn = do when verbose $ do when (optNoWriteHo options) $ putErr "Skipping " fn' <- shortenPath fn putErrLn $ "Writing haskell object file: " ++ fn' if optNoWriteHo options then return () else do let tfn = fn ++ ".tmp" cfflbs = mkCFFfile cff_magic [ (cff_jhdr, compress $ encode header { hohVersion = current_version }), (cff_idep, compress $ encode idep), (cff_defs, compress $ encode $ hoTcInfo ho), (cff_core, compress $ encode $ hoBuild ho)] LBS.writeFile tfn cfflbs renameFile tfn fn g fs recordHlFile :: Library -> IO () recordHlFile l = do --let theho = mapHoBodies eraseE ho let cfflbs = mkCFFfile cff_magic $ [ (cff_jhdr, compress $ encode (libHoHeader l) { hohVersion = current_version }), (cff_libr, compress $ encode $ libHoLib l), (cff_ldef, compress $ encode $ libTcMap l), (cff_lcor, compress $ encode $ libBuildMap l), (cff_file, compress $ encode $ libExtraFiles l)] let tfp = libFileName l ++ ".tmp" LBS.writeFile tfp cfflbs renameFile tfp $ libFileName l readHlFile :: FilePath -> IO Library readHlFile fn = do (_fn',hoh,fc) <- readHFile fn return Library { libHoHeader = hoh, libHoLib = fc cff_libr, libTcMap = fc cff_ldef, libBuildMap = fc cff_lcor, libFileName = fn, libExtraFiles = fc cff_file } instance Binary ExtraFile where put (ExtraFile a b) = put (a,b) get = do (x,y) <- get return $ ExtraFile x y instance Binary FieldMap where put (FieldMap ac ad) = do putMap ac putMap ad get = do ac <- getMap ad <- getMap return (FieldMap ac ad) instance Data.Binary.Binary HoHeader where put (HoHeader aa ab ac ad ae) = do Data.Binary.put aa Data.Binary.put ab Data.Binary.put ac Data.Binary.put ad Data.Binary.put ae get = do aa <- get ab <- get ac <- get ad <- get ae <- get return (HoHeader aa ab ac ad ae) instance Data.Binary.Binary HoIDeps where put (HoIDeps aa ab ac ad) = do Data.Binary.put aa Data.Binary.put ab Data.Binary.put ac Data.Binary.put ad get = do aa <- get ab <- get ac <- get ad <- get return (HoIDeps aa ab ac ad) instance Data.Binary.Binary HoLib where put (HoLib aa ab ac ad) = do Data.Binary.put aa Data.Binary.put ab Data.Binary.put ac Data.Binary.put ad get = do aa <- get ab <- get ac <- get ad <- get return (HoLib aa ab ac ad) instance Binary Data.Version.Version where put (Data.Version.Version a b) = put a >> put b get = liftM2 Data.Version.Version get get instance Data.Binary.Binary HoTcInfo where put (HoTcInfo aa ab ac ad ae af ag ah) = do Data.Binary.put aa putMap ab putMap ac Data.Binary.put ad Data.Binary.put ae Data.Binary.put af Data.Binary.put ag Data.Binary.put ah get = do aa <- get ab <- getMap ac <- getMap ad <- get ae <- get af <- get ag <- get ah <- get return (HoTcInfo aa ab ac ad ae af ag ah) instance Data.Binary.Binary HoBuild where put (HoBuild aa ab ac) = do Data.Binary.put aa Data.Binary.put ab Data.Binary.put ac get = do aa <- get ab <- get ac <- get return (HoBuild aa ab ac)