{-# LANGUAGE CPP                 #-}
{-# LANGUAGE ScopedTypeVariables #-}
module GHC.SysTools (
        
        initSysTools,
        lazyInitLlvmConfig,
        
        module GHC.SysTools.Tasks,
        module GHC.SysTools.Info,
        copy,
        copyWithHeader,
        
        Option(..),
        expandTopDir,
 ) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Settings.Utils
import GHC.Utils.Error
import GHC.Utils.Panic
import GHC.Utils.Logger
import GHC.Driver.Session
import Control.Monad.Trans.Except (runExceptT)
import System.FilePath
import System.IO
import System.IO.Unsafe (unsafeInterleaveIO)
import GHC.Linker.ExtraObj
import GHC.SysTools.Info
import GHC.SysTools.Tasks
import GHC.SysTools.BaseDir
import GHC.Settings.IO
lazyInitLlvmConfig :: String
               -> IO LlvmConfig
lazyInitLlvmConfig :: String -> IO LlvmConfig
lazyInitLlvmConfig String
top_dir
  = IO LlvmConfig -> IO LlvmConfig
forall a. IO a -> IO a
unsafeInterleaveIO (IO LlvmConfig -> IO LlvmConfig) -> IO LlvmConfig -> IO LlvmConfig
forall a b. (a -> b) -> a -> b
$ do    
      [(String, (String, String, String))]
targets <- String -> IO [(String, (String, String, String))]
forall a. Read a => String -> IO a
readAndParse String
"llvm-targets"
      [(Int, String)]
passes <- String -> IO [(Int, String)]
forall a. Read a => String -> IO a
readAndParse String
"llvm-passes"
      LlvmConfig -> IO LlvmConfig
forall (m :: * -> *) a. Monad m => a -> m a
return (LlvmConfig -> IO LlvmConfig) -> LlvmConfig -> IO LlvmConfig
forall a b. (a -> b) -> a -> b
$ LlvmConfig { llvmTargets :: [(String, LlvmTarget)]
llvmTargets = ((String, String, String) -> LlvmTarget)
-> (String, (String, String, String)) -> (String, LlvmTarget)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String, String, String) -> LlvmTarget
mkLlvmTarget ((String, (String, String, String)) -> (String, LlvmTarget))
-> [(String, (String, String, String))] -> [(String, LlvmTarget)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(String, (String, String, String))]
targets,
                            llvmPasses :: [(Int, String)]
llvmPasses = [(Int, String)]
passes }
  where
    readAndParse :: Read a => String -> IO a
    readAndParse :: forall a. Read a => String -> IO a
readAndParse String
name =
      do let llvmConfigFile :: String
llvmConfigFile = String
top_dir String -> String -> String
</> String
name
         String
llvmConfigStr <- String -> IO String
readFile String
llvmConfigFile
         case String -> Maybe a
forall a. Read a => String -> Maybe a
maybeReadFuzzy String
llvmConfigStr of
           Just a
s -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
s
           Maybe a
Nothing -> String -> IO a
forall a. String -> a
pgmError (String
"Can't parse " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. Show a => a -> String
show String
llvmConfigFile)
    mkLlvmTarget :: (String, String, String) -> LlvmTarget
    mkLlvmTarget :: (String, String, String) -> LlvmTarget
mkLlvmTarget (String
dl, String
cpu, String
attrs) = String -> String -> [String] -> LlvmTarget
LlvmTarget String
dl String
cpu (String -> [String]
words String
attrs)
initSysTools :: String          
             -> IO Settings     
                                
                                
                                
initSysTools :: String -> IO Settings
initSysTools String
top_dir = do
  Either SettingsError Settings
res <- ExceptT SettingsError IO Settings
-> IO (Either SettingsError Settings)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT SettingsError IO Settings
 -> IO (Either SettingsError Settings))
-> ExceptT SettingsError IO Settings
-> IO (Either SettingsError Settings)
forall a b. (a -> b) -> a -> b
$ String -> ExceptT SettingsError IO Settings
forall (m :: * -> *).
MonadIO m =>
String -> ExceptT SettingsError m Settings
initSettings String
top_dir
  case Either SettingsError Settings
res of
    Right Settings
a -> Settings -> IO Settings
forall (f :: * -> *) a. Applicative f => a -> f a
pure Settings
a
    Left (SettingsError_MissingData String
msg) -> String -> IO Settings
forall a. String -> a
pgmError String
msg
    Left (SettingsError_BadData String
msg) -> String -> IO Settings
forall a. String -> a
pgmError String
msg
copy :: Logger -> DynFlags -> String -> FilePath -> FilePath -> IO ()
copy :: Logger -> DynFlags -> String -> String -> String -> IO ()
copy Logger
logger DynFlags
dflags String
purpose String
from String
to = Logger
-> DynFlags -> String -> Maybe String -> String -> String -> IO ()
copyWithHeader Logger
logger DynFlags
dflags String
purpose Maybe String
forall a. Maybe a
Nothing String
from String
to
copyWithHeader :: Logger -> DynFlags -> String -> Maybe String -> FilePath -> FilePath
               -> IO ()
 Logger
logger DynFlags
dflags String
purpose Maybe String
maybe_header String
from String
to = do
  Logger -> DynFlags -> String -> IO ()
showPass Logger
logger DynFlags
dflags String
purpose
  Handle
hout <- String -> IOMode -> IO Handle
openBinaryFile String
to   IOMode
WriteMode
  Handle
hin  <- String -> IOMode -> IO Handle
openBinaryFile String
from IOMode
ReadMode
  String
ls <- Handle -> IO String
hGetContents Handle
hin 
  IO () -> (String -> IO ()) -> Maybe String -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (Handle -> String -> IO ()
header Handle
hout) Maybe String
maybe_header
  Handle -> String -> IO ()
hPutStr Handle
hout String
ls
  Handle -> IO ()
hClose Handle
hout
  Handle -> IO ()
hClose Handle
hin
 where
  
  
  
  header :: Handle -> String -> IO ()
header Handle
h String
str = do
   Handle -> TextEncoding -> IO ()
hSetEncoding Handle
h TextEncoding
utf8
   Handle -> String -> IO ()
hPutStr Handle
h String
str
   Handle -> Bool -> IO ()
hSetBinaryMode Handle
h Bool
True