{-# LANGUAGE CPP, RankNTypes, FlexibleContexts #-}
module Distribution.Compat.ResponseFile (expandResponse) where
import Distribution.Compat.Prelude
import Prelude ()
import System.FilePath
import System.IO (hPutStrLn, stderr)
import System.IO.Error
#if MIN_VERSION_base(4,12,0)
import GHC.ResponseFile (unescapeArgs)
#else
unescapeArgs :: String -> [String]
unescapeArgs = filter (not . null) . unescape
data Quoting = NoneQ | SngQ | DblQ
unescape :: String -> [String]
unescape args = reverse . map reverse $ go args NoneQ False [] []
where
go [] _q _bs a as = a:as
go (c:cs) q True a as = go cs q False (c:a) as
go (c:cs) q False a as
| '\\' == c = go cs q True a as
go (c:cs) SngQ False a as
| '\'' == c = go cs NoneQ False a as
| otherwise = go cs SngQ False (c:a) as
go (c:cs) DblQ False a as
| '"' == c = go cs NoneQ False a as
| otherwise = go cs DblQ False (c:a) as
go (c:cs) NoneQ False a as
| isSpace c = go cs NoneQ False [] (a:as)
| '\'' == c = go cs SngQ False a as
| '"' == c = go cs DblQ False a as
| otherwise = go cs NoneQ False (c:a) as
#endif
expandResponse :: [String] -> IO [String]
expandResponse :: [String] -> IO [String]
expandResponse = Int -> String -> [String] -> IO [String]
go Int
recursionLimit String
"."
where
recursionLimit :: Int
recursionLimit = Int
100
go :: Int -> FilePath -> [String] -> IO [String]
go :: Int -> String -> [String] -> IO [String]
go Int
n String
dir
| Int
n forall a. Ord a => a -> a -> Bool
>= Int
0 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Int -> String -> String -> IO [String]
expand Int
n String
dir)
| Bool
otherwise = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Handle -> String -> IO ()
hPutStrLn Handle
stderr String
"Error: response file recursion limit exceeded." forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall a. IO a
exitFailure
expand :: Int -> FilePath -> String -> IO [String]
expand :: Int -> String -> String -> IO [String]
expand Int
n String
dir arg :: String
arg@(Char
'@':String
f) = Int -> String -> IO [String]
readRecursively Int
n (String
dir String -> String -> String
</> String
f) forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> IO ()
print String
"?" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return [String
arg])
expand Int
_n String
_dir String
x = forall (m :: * -> *) a. Monad m => a -> m a
return [String
x]
readRecursively :: Int -> FilePath -> IO [String]
readRecursively :: Int -> String -> IO [String]
readRecursively Int
n String
f = Int -> String -> [String] -> IO [String]
go (Int
n forall a. Num a => a -> a -> a
- Int
1) (String -> String
takeDirectory String
f) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> [String]
unescapeArgs forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO String
readFile String
f