summaryrefslogtreecommitdiff
path: root/compiler/GHC/Driver/CmdLine.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Driver/CmdLine.hs')
-rw-r--r--compiler/GHC/Driver/CmdLine.hs74
1 files changed, 42 insertions, 32 deletions
diff --git a/compiler/GHC/Driver/CmdLine.hs b/compiler/GHC/Driver/CmdLine.hs
index 539f27c53e..0c4ed95618 100644
--- a/compiler/GHC/Driver/CmdLine.hs
+++ b/compiler/GHC/Driver/CmdLine.hs
@@ -1,5 +1,4 @@
-
-{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE RankNTypes #-}
-------------------------------------------------------------------------------
--
@@ -13,9 +12,8 @@
module GHC.Driver.CmdLine
(
- processArgs, OptKind(..), GhcFlagMode(..),
- CmdLineP(..), getCmdLineState, putCmdLineState,
- Flag(..), defFlag, defGhcFlag, defGhciFlag, defHiddenFlag,
+ processArgs, parseResponseFile, OptKind(..), GhcFlagMode(..),
+ Flag(..), defFlag, defGhcFlag, defGhciFlag, defHiddenFlag, hoistFlag,
errorsToGhcException,
Err(..), Warn(..), WarnReason(..),
@@ -38,7 +36,10 @@ import GHC.Types.Error ( DiagnosticReason(..) )
import Data.Function
import Data.List (sortBy, intercalate, stripPrefix)
+import GHC.ResponseFile
+import Control.Exception (IOException, catch)
import Control.Monad (liftM, ap)
+import Control.Monad.IO.Class
--------------------------------------------------------
-- The Flag and OptKind types
@@ -62,6 +63,24 @@ defGhciFlag name optKind = Flag name optKind OnlyGhci
defHiddenFlag :: String -> OptKind m -> Flag m
defHiddenFlag name optKind = Flag name optKind HiddenFlag
+hoistFlag :: forall m n. (forall a. m a -> n a) -> Flag m -> Flag n
+hoistFlag f (Flag a b c) = Flag a (go b) c
+ where
+ go (NoArg k) = NoArg (go2 k)
+ go (HasArg k) = HasArg (\s -> go2 (k s))
+ go (SepArg k) = SepArg (\s -> go2 (k s))
+ go (Prefix k) = Prefix (\s -> go2 (k s))
+ go (OptPrefix k) = OptPrefix (\s -> go2 (k s))
+ go (OptIntSuffix k) = OptIntSuffix (\n -> go2 (k n))
+ go (IntSuffix k) = IntSuffix (\n -> go2 (k n))
+ go (WordSuffix k) = WordSuffix (\s -> go2 (k s))
+ go (FloatSuffix k) = FloatSuffix (\s -> go2 (k s))
+ go (PassFlag k) = PassFlag (\s -> go2 (k s))
+ go (AnySuffix k) = AnySuffix (\s -> go2 (k s))
+
+ go2 :: EwM m a -> EwM n a
+ go2 (EwM g) = EwM $ \loc es ws -> f (g loc es ws)
+
-- | GHC flag modes describing when a flag has an effect.
data GhcFlagMode
= OnlyGhc -- ^ The flag only affects the non-interactive GHC
@@ -130,6 +149,8 @@ instance Monad m => Applicative (EwM m) where
instance Monad m => Monad (EwM m) where
(EwM f) >>= k = EwM (\l e w -> do (e', w', r) <- f l e w
unEwM (k r) l e' w')
+instance MonadIO m => MonadIO (EwM m) where
+ liftIO = liftEwM . liftIO
runEwM :: EwM m a -> m (Errs, Warns, a)
runEwM action = unEwM action (panic "processArgs: no arg yet") emptyBag emptyBag
@@ -158,40 +179,17 @@ liftEwM action = EwM (\_ es ws -> do { r <- action; return (es, ws, r) })
--------------------------------------------------------
--- A state monad for use in the command-line parser
---------------------------------------------------------
-
--- (CmdLineP s) typically instantiates the 'm' in (EwM m) and (OptKind m)
-newtype CmdLineP s a = CmdLineP { runCmdLine :: s -> (a, s) }
- deriving (Functor)
-
-instance Applicative (CmdLineP s) where
- pure a = CmdLineP $ \s -> (a, s)
- (<*>) = ap
-
-instance Monad (CmdLineP s) where
- m >>= k = CmdLineP $ \s ->
- let (a, s') = runCmdLine m s
- in runCmdLine (k a) s'
-
-
-getCmdLineState :: CmdLineP s s
-getCmdLineState = CmdLineP $ \s -> (s,s)
-putCmdLineState :: s -> CmdLineP s ()
-putCmdLineState s = CmdLineP $ \_ -> ((),s)
-
-
---------------------------------------------------------
-- Processing arguments
--------------------------------------------------------
processArgs :: Monad m
- => [Flag m] -- cmdline parser spec
- -> [Located String] -- args
+ => [Flag m] -- ^ cmdline parser spec
+ -> [Located String] -- ^ args
+ -> (FilePath -> EwM m [Located String]) -- ^ response file handler
-> m ( [Located String], -- spare args
[Err], -- errors
[Warn] ) -- warnings
-processArgs spec args = do
+processArgs spec args handleRespFile = do
(errs, warns, spare) <- runEwM action
return (spare, bagToList errs, bagToList warns)
where
@@ -200,6 +198,10 @@ processArgs spec args = do
-- process :: [Located String] -> [Located String] -> EwM m [Located String]
process [] spare = return (reverse spare)
+ process (L _ ('@' : resp_file) : args) spare = do
+ resp_args <- handleRespFile resp_file
+ process (resp_args ++ args) spare
+
process (locArg@(L _ ('-' : arg)) : args) spare =
case findArg spec arg of
Just (rest, opt_kind) ->
@@ -319,6 +321,14 @@ missingArgErr f = Left ("missing argument for flag: " ++ f)
-- Utils
--------------------------------------------------------
+-- | Parse a response file into arguments.
+parseResponseFile :: MonadIO m => FilePath -> EwM m [Located String]
+parseResponseFile path = do
+ res <- liftIO $ fmap Right (readFile path) `catch`
+ \(e :: IOException) -> pure (Left e)
+ case res of
+ Left _err -> addErr "Could not open response file" >> return []
+ Right resp_file -> return $ map (mkGeneralLocated path) (unescapeArgs resp_file)
-- See Note [Handling errors when parsing command-line flags]
errorsToGhcException :: [(String, -- Location