    {-# LANGUAGE CPP #-}
    module Distribution.Simple.UUAGC.UUAGC(uuagcUserHook,
                                           uuagcUserHook',
                                           uuagc,
                                           uuagcLibUserHook,
                                           uuagcFromString
                                          ) where

    -- import Distribution.Simple.BuildPaths (autogenComponentModulesDir)
    import Debug.Trace
    import Distribution.Simple
    import Distribution.Simple.PreProcess
    import Distribution.Simple.LocalBuildInfo
    import Distribution.Simple.Utils
    import Distribution.Simple.Setup
    import Distribution.PackageDescription hiding (Flag)
    import Distribution.Simple.UUAGC.AbsSyn( AGFileOption(..)
                                             , AGFileOptions
                                             , AGOptionsClass(..)
                                             , lookupFileOptions
                                             , fileClasses
                                             )
    import Distribution.Simple.UUAGC.Parser
    import Options hiding (verbose)
    import Distribution.Verbosity
    import System.Process( readProcessWithExitCode )
    import System.Directory(getModificationTime
                           ,doesFileExist
                           ,removeFile)
    import System.FilePath(pathSeparators,
                           (</>),
                           takeFileName,
                           normalise,
                           joinPath,
                           dropFileName,
                           addExtension,
                           dropExtension,
                           replaceExtension,
                           splitDirectories)

    import System.Exit (ExitCode(..))
    import System.IO( openFile, IOMode(..),
                      hFileSize,
                      hSetFileSize,
                      hClose,
                      hGetContents,
                      hFlush,
                      Handle(..), stderr, hPutStr, hPutStrLn)
    import System.Exit(exitFailure)
    import Control.Exception (throwIO)
    import Control.Monad (liftM, when, guard, forM_, forM)
    import Control.Arrow ((&&&), second)
    import Data.Maybe (maybeToList)
    import Data.Either (partitionEithers)
    import Data.List (nub,intersperse)
    import Data.Map (Map)
    import qualified Data.Map as Map

    {-# DEPRECATED uuagcUserHook, uuagcUserHook', uuagc "Use uuagcLibUserHook instead" #-}

    -- | 'uuagc' returns the name of the uuagc compiler
    uuagcn :: [Char]
    uuagcn = "uuagc"

    -- | 'defUUAGCOptions' returns the default names of the uuagc options
    defUUAGCOptions :: String
    defUUAGCOptions :: [Char]
    defUUAGCOptions = "uuagc_options"

    -- | File used to store de classes defined in the cabal file.
    agClassesFile :: String
    agClassesFile :: [Char]
    agClassesFile = "ag_file_options"

    -- | The prefix used for the cabal file optionsw
    agModule :: String
    agModule :: [Char]
    agModule = "x-agmodule"

    -- | The prefix used for the cabal file options used for defining classes
    agClass :: String
    agClass :: [Char]
    agClass  = "x-agclass"

    -- | Deprecated userhook
    uuagcUserHook :: UserHooks
    uuagcUserHook :: UserHooks
    uuagcUserHook = [Char] -> UserHooks
    uuagcUserHook' [Char]
    uuagcn

    -- | Deprecated userhook
    uuagcUserHook' :: String -> UserHooks
    uuagcUserHook' :: [Char] -> UserHooks
    uuagcUserHook' uuagcPath :: [Char]
    uuagcPath = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]])) -> UserHooks
    uuagcLibUserHook ([Char] -> [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagcFromString [Char]
    uuagcPath)

    -- | Create uuagc function using shell (old method)
    uuagcFromString :: String -> [String] -> FilePath -> IO (ExitCode, [FilePath])
    uuagcFromString :: [Char] -> [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagcFromString uuagcPath :: [Char]
    uuagcPath args :: [[Char]]
    args file :: [Char]
    file = do
      (ec :: ExitCode
    ec,out :: [Char]
    out,err :: [Char]
    err) <- [Char] -> [[Char]] -> [Char] -> IO (ExitCode, [Char], [Char])
    readProcessWithExitCode [Char]
    uuagcPath ([[Char]]
    args [[Char]] -> [[Char]] -> [[Char]]
    forall a. [a] -> [a] -> [a]
    ++ [[Char]
    file]) ""
      case ExitCode
    ec of
        ExitSuccess ->
          do Handle -> [Char] -> IO ()
    hPutStr Handle
    stderr [Char]
    err
             (ExitCode, [[Char]]) -> IO (ExitCode, [[Char]])
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ExitCode
    ExitSuccess, [Char] -> [[Char]]
    words [Char]
    out)
        (ExitFailure exc :: Int
    exc) ->
          do Handle -> [Char] -> IO ()
    hPutStrLn Handle
    stderr ([Char]
    uuagcPath [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ ": " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ Int -> [Char]
    forall a. Show a => a -> [Char]
    show Int
    exc)
             Handle -> [Char] -> IO ()
    hPutStr Handle
    stderr [Char]
    out
             Handle -> [Char] -> IO ()
    hPutStr Handle
    stderr [Char]
    err
             (ExitCode, [[Char]]) -> IO (ExitCode, [[Char]])
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> ExitCode
    ExitFailure Int
    exc, [])

    -- | Main hook, argument should be uuagc function
    uuagcLibUserHook :: ([String] -> FilePath -> IO (ExitCode, [FilePath])) -> UserHooks
    uuagcLibUserHook :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]])) -> UserHooks
    uuagcLibUserHook uuagc :: [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc = UserHooks
    hooks where
      hooks :: UserHooks
    hooks = UserHooks
    simpleUserHooks { hookedPreProcessors :: [PPSuffixHandler]
    hookedPreProcessors = ("ag", BuildInfo
    -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    ag)PPSuffixHandler -> [PPSuffixHandler] -> [PPSuffixHandler]
    forall a. a -> [a] -> [a]
    :("lag",BuildInfo
    -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    ag)PPSuffixHandler -> [PPSuffixHandler] -> [PPSuffixHandler]
    forall a. a -> [a] -> [a]
    :[PPSuffixHandler]
    knownSuffixHandlers
                              , buildHook :: PackageDescription
    -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
    buildHook = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> PackageDescription
    -> LocalBuildInfo
    -> UserHooks
    -> BuildFlags
    -> IO ()
    uuagcBuildHook [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc
    --                          , sDistHook = uuagcSDistHook uuagc
                              }
      ag :: BuildInfo
    -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    ag = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> BuildInfo
    -> LocalBuildInfo
    -> ComponentLocalBuildInfo
    -> PreProcessor
    uuagc' [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc

    originalPreBuild :: [[Char]] -> BuildFlags -> IO HookedBuildInfo
    originalPreBuild  = UserHooks -> [[Char]] -> BuildFlags -> IO HookedBuildInfo
    preBuild UserHooks
    simpleUserHooks
    originalBuildHook :: PackageDescription
    -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
    originalBuildHook = UserHooks
    -> PackageDescription
    -> LocalBuildInfo
    -> UserHooks
    -> BuildFlags
    -> IO ()
    buildHook UserHooks
    simpleUserHooks
    --originalSDistHook = sDistHook simpleUserHooks

    putErrorInfo :: Handle -> IO ()
    putErrorInfo :: Handle -> IO ()
    putErrorInfo h :: Handle
    h = Handle -> IO [Char]
    hGetContents Handle
    h IO [Char] -> ([Char] -> IO ()) -> IO ()
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Handle -> [Char] -> IO ()
    hPutStr Handle
    stderr

    -- | 'updateAGFile' search into the uuagc options file for a list of all
    -- AG Files and theirs file dependencies in order to see if the latters
    -- are more updated that the formers, and if this is the case to
    -- update the AG File
    updateAGFile :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
                 -> Map FilePath (Options, Maybe (FilePath, [String]))
                 -> (FilePath, (Options, Maybe (FilePath, [String])))
                 -> IO ()
    updateAGFile :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> ([Char], (Options, Maybe ([Char], [[Char]])))
    -> IO ()
    updateAGFile _ _ (_,(_,Nothing)) = () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    updateAGFile uuagc :: [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc newOptions :: Map [Char] (Options, Maybe ([Char], [[Char]]))
    newOptions (file :: [Char]
    file,(opts :: Options
    opts,Just (gen :: [Char]
    gen,sp :: [[Char]]
    sp))) = do
      Bool
    hasGen <- [Char] -> IO Bool
    doesFileExist [Char]
    gen
      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    hasGen (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
        (ec :: ExitCode
    ec, files :: [[Char]]
    files) <- [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc (Options -> [[Char]]
    optionsToString (Options -> [[Char]]) -> Options -> [[Char]]
    forall a b. (a -> b) -> a -> b
    $ Options
    opts { genFileDeps :: Bool
    genFileDeps = Bool
    True, searchPath :: [[Char]]
    searchPath = [[Char]]
    sp }) [Char]
    file
        case ExitCode
    ec of
          ExitSuccess -> do
            let newOpts :: Options
                newOpts :: Options
    newOpts = Options
    -> ((Options, Maybe ([Char], [[Char]])) -> Options)
    -> Maybe (Options, Maybe ([Char], [[Char]]))
    -> Options
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Options
    noOptions (Options, Maybe ([Char], [[Char]])) -> Options
    forall a b. (a, b) -> a
    fst (Maybe (Options, Maybe ([Char], [[Char]])) -> Options)
    -> Maybe (Options, Maybe ([Char], [[Char]])) -> Options
    forall a b. (a -> b) -> a -> b
    $ [Char]
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> Maybe (Options, Maybe ([Char], [[Char]]))
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup [Char]
    file Map [Char] (Options, Maybe ([Char], [[Char]]))
    newOptions
                optRebuild :: Bool
    optRebuild = Options -> [[Char]]
    optionsToString Options
    newOpts [[Char]] -> [[Char]] -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Options -> [[Char]]
    optionsToString Options
    opts
            Bool
    modRebuild <-
              if [[Char]] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [[Char]]
    files
              then Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
              else do
                [UTCTime]
    flsmt <- ([Char] -> IO UTCTime) -> [[Char]] -> IO [UTCTime]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM [Char] -> IO UTCTime
    getModificationTime [[Char]]
    files
                let maxModified :: UTCTime
    maxModified = [UTCTime] -> UTCTime
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    maximum [UTCTime]
    flsmt
                UTCTime
    fmt <- [Char] -> IO UTCTime
    getModificationTime [Char]
    gen
                Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool -> IO Bool) -> Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ UTCTime
    maxModified UTCTime -> UTCTime -> Bool
    forall a. Ord a => a -> a -> Bool
    > UTCTime
    fmt
            -- When some dependency is newer or options have changed, we should regenerate
            Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Bool
    optRebuild Bool -> Bool -> Bool
    || Bool
    modRebuild) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ [Char] -> IO ()
    removeFile [Char]
    gen
          ex :: ExitCode
    ex@(ExitFailure _) -> ExitCode -> IO ()
    forall e a. Exception e => e -> IO a
    throwIO ExitCode
    ex

    getAGFileOptions :: [(String, String)] -> IO AGFileOptions
    getAGFileOptions :: [([Char], [Char])] -> IO AGFileOptions
    getAGFileOptions extra :: [([Char], [Char])]
    extra = do
      AGFileOptions
    cabalOpts <- (([Char], [Char]) -> IO AGFileOption)
    -> [([Char], [Char])] -> IO AGFileOptions
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM ([Char] -> IO AGFileOption
    parseOptionAG ([Char] -> IO AGFileOption)
    -> (([Char], [Char]) -> [Char])
    -> ([Char], [Char])
    -> IO AGFileOption
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], [Char]) -> [Char]
    forall a b. (a, b) -> b
    snd) ([([Char], [Char])] -> IO AGFileOptions)
    -> [([Char], [Char])] -> IO AGFileOptions
    forall a b. (a -> b) -> a -> b
    $ (([Char], [Char]) -> Bool)
    -> [([Char], [Char])] -> [([Char], [Char])]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (([Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    agModule) ([Char] -> Bool)
    -> (([Char], [Char]) -> [Char]) -> ([Char], [Char]) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], [Char]) -> [Char]
    forall a b. (a, b) -> a
    fst) [([Char], [Char])]
    extra
      Bool
    usesOptionsFile <- [Char] -> IO Bool
    doesFileExist [Char]
    defUUAGCOptions
      if Bool
    usesOptionsFile
           then do Either ParserError AGFileOptions
    r <- [Char] -> IO (Either ParserError AGFileOptions)
    parserAG' [Char]
    defUUAGCOptions
                   case Either ParserError AGFileOptions
    r of
                     Left e :: ParserError
    e -> [Char] -> IO AGFileOptions
    forall a. [Char] -> IO a
    dieNoVerbosity (ParserError -> [Char]
    forall a. Show a => a -> [Char]
    show ParserError
    e)
                     Right a :: AGFileOptions
    a -> AGFileOptions -> IO AGFileOptions
    forall (m :: * -> *) a. Monad m => a -> m a
    return (AGFileOptions -> IO AGFileOptions)
    -> AGFileOptions -> IO AGFileOptions
    forall a b. (a -> b) -> a -> b
    $ AGFileOptions
    cabalOpts AGFileOptions -> AGFileOptions -> AGFileOptions
    forall a. [a] -> [a] -> [a]
    ++ AGFileOptions
    a
           else AGFileOptions -> IO AGFileOptions
    forall (m :: * -> *) a. Monad m => a -> m a
    return AGFileOptions
    cabalOpts

    getAGClasses :: [(String, String)] -> IO [AGOptionsClass]
    getAGClasses :: [([Char], [Char])] -> IO [AGOptionsClass]
    getAGClasses = (([Char], [Char]) -> IO AGOptionsClass)
    -> [([Char], [Char])] -> IO [AGOptionsClass]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM ([Char] -> IO AGOptionsClass
    parseClassAG ([Char] -> IO AGOptionsClass)
    -> (([Char], [Char]) -> [Char])
    -> ([Char], [Char])
    -> IO AGOptionsClass
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], [Char]) -> [Char]
    forall a b. (a, b) -> b
    snd) ([([Char], [Char])] -> IO [AGOptionsClass])
    -> ([([Char], [Char])] -> [([Char], [Char])])
    -> [([Char], [Char])]
    -> IO [AGOptionsClass]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (([Char], [Char]) -> Bool)
    -> [([Char], [Char])] -> [([Char], [Char])]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (([Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    agClass) ([Char] -> Bool)
    -> (([Char], [Char]) -> [Char]) -> ([Char], [Char]) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], [Char]) -> [Char]
    forall a b. (a, b) -> a
    fst)

    writeFileOptions :: FilePath -> Map FilePath (Options, Maybe (FilePath,[String])) -> IO ()
    writeFileOptions :: [Char] -> Map [Char] (Options, Maybe ([Char], [[Char]])) -> IO ()
    writeFileOptions classesPath :: [Char]
    classesPath opts :: Map [Char] (Options, Maybe ([Char], [[Char]]))
    opts  = do
      Handle
    hClasses <- [Char] -> IOMode -> IO Handle
    openFile [Char]
    classesPath IOMode
    WriteMode
      Handle -> [Char] -> IO ()
    hPutStr Handle
    hClasses ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Map [Char] ([[Char]], Maybe ([Char], [[Char]])) -> [Char]
    forall a. Show a => a -> [Char]
    show (Map [Char] ([[Char]], Maybe ([Char], [[Char]])) -> [Char])
    -> Map [Char] ([[Char]], Maybe ([Char], [[Char]])) -> [Char]
    forall a b. (a -> b) -> a -> b
    $ ((Options, Maybe ([Char], [[Char]]))
     -> ([[Char]], Maybe ([Char], [[Char]])))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> Map [Char] ([[Char]], Maybe ([Char], [[Char]]))
    forall a b k. (a -> b) -> Map k a -> Map k b
    Map.map (\(opt :: Options
    opt,gen :: Maybe ([Char], [[Char]])
    gen) -> (Options -> [[Char]]
    optionsToString Options
    opt, Maybe ([Char], [[Char]])
    gen)) Map [Char] (Options, Maybe ([Char], [[Char]]))
    opts
      Handle -> IO ()
    hFlush  Handle
    hClasses
      Handle -> IO ()
    hClose  Handle
    hClasses

    readFileOptions :: FilePath -> IO (Map FilePath (Options, Maybe (FilePath,[String])))
    readFileOptions :: [Char] -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
    readFileOptions classesPath :: [Char]
    classesPath = do
      Bool
    isFile <- [Char] -> IO Bool
    doesFileExist [Char]
    classesPath
      if Bool
    isFile
        then do Handle
    hClasses <- [Char] -> IOMode -> IO Handle
    openFile [Char]
    classesPath IOMode
    ReadMode
                [Char]
    sClasses <- Handle -> IO [Char]
    hGetContents Handle
    hClasses
                Map [Char] ([[Char]], Maybe ([Char], [[Char]]))
    classes <- [Char] -> IO (Map [Char] ([[Char]], Maybe ([Char], [[Char]])))
    forall a. Read a => [Char] -> IO a
    readIO [Char]
    sClasses :: IO (Map FilePath ([String], Maybe (FilePath,[String])))
                Handle -> IO ()
    hClose Handle
    hClasses
                Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Map [Char] (Options, Maybe ([Char], [[Char]]))
     -> IO (Map [Char] (Options, Maybe ([Char], [[Char]]))))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
    forall a b. (a -> b) -> a -> b
    $ (([[Char]], Maybe ([Char], [[Char]]))
     -> (Options, Maybe ([Char], [[Char]])))
    -> Map [Char] ([[Char]], Maybe ([Char], [[Char]]))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    forall a b k. (a -> b) -> Map k a -> Map k b
    Map.map (\(opt :: [[Char]]
    opt,gen :: Maybe ([Char], [[Char]])
    gen) -> let (opt' :: Options
    opt',_,_) = [[Char]] -> (Options, [[Char]], [[Char]])
    getOptions [[Char]]
    opt in (Options
    opt', Maybe ([Char], [[Char]])
    gen)) Map [Char] ([[Char]], Maybe ([Char], [[Char]]))
    classes
        else    Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Map [Char] (Options, Maybe ([Char], [[Char]]))
    forall k a. Map k a
    Map.empty

    getOptionsFromClass :: [(String, Options)] -> AGFileOption -> ([String], Options)
    getOptionsFromClass :: [([Char], Options)] -> AGFileOption -> ([[Char]], Options)
    getOptionsFromClass classes :: [([Char], Options)]
    classes fOpt :: AGFileOption
    fOpt =
        ([Options] -> Options)
    -> ([[Char]], [Options]) -> ([[Char]], Options)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (d, b) (d, c)
    second ((Options -> Options -> Options) -> Options -> [Options] -> Options
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl Options -> Options -> Options
    combineOptions (AGFileOption -> Options
    opts AGFileOption
    fOpt))
        (([[Char]], [Options]) -> ([[Char]], Options))
    -> ([Either [Char] Options] -> ([[Char]], [Options]))
    -> [Either [Char] Options]
    -> ([[Char]], Options)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Either [Char] Options] -> ([[Char]], [Options])
    forall a b. [Either a b] -> ([a], [b])
    partitionEithers ([Either [Char] Options] -> ([[Char]], Options))
    -> [Either [Char] Options] -> ([[Char]], Options)
    forall a b. (a -> b) -> a -> b
    $ do
                           [Char]
    fClass <- AGFileOption -> [[Char]]
    fileClasses AGFileOption
    fOpt
                           case [Char]
    fClass [Char] -> [([Char], Options)] -> Maybe Options
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    `lookup` [([Char], Options)]
    classes of
                             Just x :: Options
    x  -> Either [Char] Options -> [Either [Char] Options]
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either [Char] Options -> [Either [Char] Options])
    -> Either [Char] Options -> [Either [Char] Options]
    forall a b. (a -> b) -> a -> b
    $ Options -> Either [Char] Options
    forall a b. b -> Either a b
    Right Options
    x
                             Nothing -> Either [Char] Options -> [Either [Char] Options]
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either [Char] Options -> [Either [Char] Options])
    -> Either [Char] Options -> [Either [Char] Options]
    forall a b. (a -> b) -> a -> b
    $ [Char] -> Either [Char] Options
    forall a b. a -> Either a b
    Left ([Char] -> Either [Char] Options)
    -> [Char] -> Either [Char] Options
    forall a b. (a -> b) -> a -> b
    $ "Warning: The class "
                                                       [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char] -> [Char]
    forall a. Show a => a -> [Char]
    show [Char]
    fClass
                                                       [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ " is not defined."

    -- uuagcSDistHook :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
    --      -> PackageDescription
    --      -> Maybe LocalBuildInfo
    --      -> UserHooks
    --      -> SDistFlags
    --      -> IO ()
    -- uuagcSDistHook uuagc pd mbLbi uh df = do
    --   {-
    --   case mbLbi of
    --     Nothing -> warn normal "sdist: the local buildinfo was not present. Skipping AG initialization. Dist may fail."
    --     Just lbi -> let classesPath = buildDir lbi </> agClassesFile
    --                 in commonHook uuagc classesPath pd lbi (sDistVerbosity df)
    --   originalSDistHook pd mbLbi uh df
    --   -}
    --   originalSDistHook pd mbLbi (uh { hookedPreProcessors = ("ag", nouuagc):("lag",nouuagc):knownSuffixHandlers }) df  -- bypass preprocessors

    uuagcBuildHook
      :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
         -> PackageDescription
         -> LocalBuildInfo
         -> UserHooks
         -> BuildFlags
         -> IO ()
    uuagcBuildHook :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> PackageDescription
    -> LocalBuildInfo
    -> UserHooks
    -> BuildFlags
    -> IO ()
    uuagcBuildHook uuagc :: [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc pd :: PackageDescription
    pd lbi :: LocalBuildInfo
    lbi uh :: UserHooks
    uh bf :: BuildFlags
    bf = do
      let classesPath :: [Char]
    classesPath = LocalBuildInfo -> [Char]
    buildDir LocalBuildInfo
    lbi [Char] -> [Char] -> [Char]
    </> [Char]
    agClassesFile
      ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> [Char]
    -> PackageDescription
    -> LocalBuildInfo
    -> Flag Verbosity
    -> IO ()
    commonHook [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc [Char]
    classesPath PackageDescription
    pd LocalBuildInfo
    lbi (BuildFlags -> Flag Verbosity
    buildVerbosity BuildFlags
    bf)
      PackageDescription
    -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
    originalBuildHook PackageDescription
    pd LocalBuildInfo
    lbi UserHooks
    uh BuildFlags
    bf

    commonHook :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
         -> FilePath
         -> PackageDescription
         -> LocalBuildInfo
         -> Flag Verbosity
         -> IO ()
    commonHook :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> [Char]
    -> PackageDescription
    -> LocalBuildInfo
    -> Flag Verbosity
    -> IO ()
    commonHook uuagc :: [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc classesPath :: [Char]
    classesPath pd :: PackageDescription
    pd lbi :: LocalBuildInfo
    lbi fl :: Flag Verbosity
    fl = do
      let verbosity :: Verbosity
    verbosity = Verbosity -> Flag Verbosity -> Verbosity
    forall a. a -> Flag a -> a
    fromFlagOrDefault Verbosity
    normal Flag Verbosity
    fl
      Verbosity -> [Char] -> IO ()
    info Verbosity
    verbosity ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ "commonHook: Assuming AG classesPath: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    classesPath
      Verbosity -> Bool -> [Char] -> IO ()
    createDirectoryIfMissingVerbose Verbosity
    verbosity Bool
    True (LocalBuildInfo -> [Char]
    buildDir LocalBuildInfo
    lbi)
      -- Read already existing options
      -- Map FilePath (Options, Maybe (FilePath,[String]))
      Map [Char] (Options, Maybe ([Char], [[Char]]))
    oldOptions <- [Char] -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
    readFileOptions [Char]
    classesPath
      -- Read options from cabal and settings file
      let lib :: Maybe Library
    lib    = PackageDescription -> Maybe Library
    library PackageDescription
    pd
          exes :: [Executable]
    exes   = PackageDescription -> [Executable]
    executables PackageDescription
    pd
          bis :: [BuildInfo]
    bis    = (Library -> BuildInfo) -> [Library] -> [BuildInfo]
    forall a b. (a -> b) -> [a] -> [b]
    map Library -> BuildInfo
    libBuildInfo (Maybe Library -> [Library]
    forall a. Maybe a -> [a]
    maybeToList Maybe Library
    lib) [BuildInfo] -> [BuildInfo] -> [BuildInfo]
    forall a. [a] -> [a] -> [a]
    ++ (Executable -> BuildInfo) -> [Executable] -> [BuildInfo]
    forall a b. (a -> b) -> [a] -> [b]
    map Executable -> BuildInfo
    buildInfo [Executable]
    exes
      [([Char], Options)]
    classes <- (AGOptionsClass -> ([Char], Options))
    -> [AGOptionsClass] -> [([Char], Options)]
    forall a b. (a -> b) -> [a] -> [b]
    map (AGOptionsClass -> [Char]
    className (AGOptionsClass -> [Char])
    -> (AGOptionsClass -> Options)
    -> AGOptionsClass
    -> ([Char], Options)
    forall (a :: * -> * -> *) b c c'.
    Arrow a =>
    a b c -> a b c' -> a b (c, c')
    &&& AGOptionsClass -> Options
    opts') ([AGOptionsClass] -> [([Char], Options)])
    -> IO [AGOptionsClass] -> IO [([Char], Options)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` ([([Char], [Char])] -> IO [AGOptionsClass]
    getAGClasses ([([Char], [Char])] -> IO [AGOptionsClass])
    -> (PackageDescription -> [([Char], [Char])])
    -> PackageDescription
    -> IO [AGOptionsClass]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PackageDescription -> [([Char], [Char])]
    customFieldsPD (PackageDescription -> IO [AGOptionsClass])
    -> PackageDescription -> IO [AGOptionsClass]
    forall a b. (a -> b) -> a -> b
    $ PackageDescription
    pd)
      AGFileOptions
    configOptions <- [([Char], [Char])] -> IO AGFileOptions
    getAGFileOptions ([BuildInfo]
    bis [BuildInfo]
    -> (BuildInfo -> [([Char], [Char])]) -> [([Char], [Char])]
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BuildInfo -> [([Char], [Char])]
    customFieldsBI)
      -- Construct new options map
      [([Char], (Options, Maybe ([Char], [[Char]])))]
    newOptionsL <- AGFileOptions
    -> (AGFileOption
        -> IO ([Char], (Options, Maybe ([Char], [[Char]]))))
    -> IO [([Char], (Options, Maybe ([Char], [[Char]])))]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    t a -> (a -> m b) -> m (t b)
    forM AGFileOptions
    configOptions (\ opt :: AGFileOption
    opt ->
          let (notFound :: [[Char]]
    notFound, opts :: Options
    opts) = [([Char], Options)] -> AGFileOption -> ([[Char]], Options)
    getOptionsFromClass [([Char], Options)]
    classes (AGFileOption -> ([[Char]], Options))
    -> AGFileOption -> ([[Char]], Options)
    forall a b. (a -> b) -> a -> b
    $ AGFileOption
    opt
              file :: [Char]
    file = [Char] -> [Char]
    normalise ([Char] -> [Char]) -> [Char] -> [Char]
    forall a b. (a -> b) -> a -> b
    $ AGFileOption -> [Char]
    filename AGFileOption
    opt
              gen :: Maybe ([Char], [[Char]])
    gen = Maybe ([Char], [[Char]])
    -> ((Options, Maybe ([Char], [[Char]]))
        -> Maybe ([Char], [[Char]]))
    -> Maybe (Options, Maybe ([Char], [[Char]]))
    -> Maybe ([Char], [[Char]])
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Maybe ([Char], [[Char]])
    forall a. Maybe a
    Nothing (Options, Maybe ([Char], [[Char]])) -> Maybe ([Char], [[Char]])
    forall a b. (a, b) -> b
    snd (Maybe (Options, Maybe ([Char], [[Char]]))
     -> Maybe ([Char], [[Char]]))
    -> Maybe (Options, Maybe ([Char], [[Char]]))
    -> Maybe ([Char], [[Char]])
    forall a b. (a -> b) -> a -> b
    $ [Char]
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> Maybe (Options, Maybe ([Char], [[Char]]))
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup [Char]
    file Map [Char] (Options, Maybe ([Char], [[Char]]))
    oldOptions
          in do Verbosity -> [Char] -> IO ()
    info Verbosity
    verbosity ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ "options for " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    file [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ ": " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [[Char]] -> [Char]
    unwords (Options -> [[Char]]
    optionsToString Options
    opts)
                [[Char]] -> ([Char] -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [[Char]]
    notFound (Handle -> [Char] -> IO ()
    hPutStrLn Handle
    stderr)
                ([Char], (Options, Maybe ([Char], [[Char]])))
    -> IO ([Char], (Options, Maybe ([Char], [[Char]])))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Char]
    file, (Options
    opts, Maybe ([Char], [[Char]])
    gen)))
      let newOptions :: Map [Char] (Options, Maybe ([Char], [[Char]]))
    newOptions = [([Char], (Options, Maybe ([Char], [[Char]])))]
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [([Char], (Options, Maybe ([Char], [[Char]])))]
    newOptionsL
      [Char] -> Map [Char] (Options, Maybe ([Char], [[Char]])) -> IO ()
    writeFileOptions [Char]
    classesPath Map [Char] (Options, Maybe ([Char], [[Char]]))
    newOptions
      -- Check if files should be regenerated
      (([Char], (Options, Maybe ([Char], [[Char]]))) -> IO ())
    -> [([Char], (Options, Maybe ([Char], [[Char]])))] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> ([Char], (Options, Maybe ([Char], [[Char]])))
    -> IO ()
    updateAGFile [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc Map [Char] (Options, Maybe ([Char], [[Char]]))
    newOptions) ([([Char], (Options, Maybe ([Char], [[Char]])))] -> IO ())
    -> [([Char], (Options, Maybe ([Char], [[Char]])))] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> [([Char], (Options, Maybe ([Char], [[Char]])))]
    forall k a. Map k a -> [(k, a)]
    Map.toList Map [Char] (Options, Maybe ([Char], [[Char]]))
    oldOptions

    getAGFileList :: AGFileOptions -> [FilePath]
    getAGFileList :: AGFileOptions -> [[Char]]
    getAGFileList = (AGFileOption -> [Char]) -> AGFileOptions -> [[Char]]
    forall a b. (a -> b) -> [a] -> [b]
    map ([Char] -> [Char]
    normalise ([Char] -> [Char])
    -> (AGFileOption -> [Char]) -> AGFileOption -> [Char]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . AGFileOption -> [Char]
    filename)

    uuagc :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    uuagc :: BuildInfo
    -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    uuagc = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> BuildInfo
    -> LocalBuildInfo
    -> ComponentLocalBuildInfo
    -> PreProcessor
    uuagc' ([Char] -> [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagcFromString [Char]
    uuagcn)

    uuagc' :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
            -> BuildInfo
            -> LocalBuildInfo
            -> ComponentLocalBuildInfo
            -> PreProcessor
    uuagc' :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
    -> BuildInfo
    -> LocalBuildInfo
    -> ComponentLocalBuildInfo
    -> PreProcessor
    uuagc' uuagc :: [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc build :: BuildInfo
    build lbi :: LocalBuildInfo
    lbi _ =
       PreProcessor :: Bool
    -> (([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ())
    -> PreProcessor
    PreProcessor {
         platformIndependent :: Bool
    platformIndependent = Bool
    True,
         runPreProcessor :: ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
    runPreProcessor = ([Char] -> [Char] -> Verbosity -> IO ())
    -> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
    ([Char] -> [Char] -> Verbosity -> IO ())
    -> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
    mkSimplePreProcessor (([Char] -> [Char] -> Verbosity -> IO ())
     -> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ())
    -> ([Char] -> [Char] -> Verbosity -> IO ())
    -> ([Char], [Char])
    -> ([Char], [Char])
    -> Verbosity
    -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \ inFile :: [Char]
    inFile outFile :: [Char]
    outFile verbosity :: Verbosity
    verbosity ->
                           do Verbosity -> [Char] -> IO ()
    notice Verbosity
    verbosity ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ "[UUAGC] processing: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    inFile [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ " generating: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    outFile
                              let classesPath :: [Char]
    classesPath = LocalBuildInfo -> [Char]
    buildDir LocalBuildInfo
    lbi [Char] -> [Char] -> [Char]
    </> [Char]
    agClassesFile
                              Verbosity -> [Char] -> IO ()
    info Verbosity
    verbosity ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ "uuagc-preprocessor: Assuming AG classesPath: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    classesPath
                              Map [Char] (Options, Maybe ([Char], [[Char]]))
    fileOpts <- [Char] -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
    readFileOptions [Char]
    classesPath
                              Options
    opts <- case [Char]
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> Maybe (Options, Maybe ([Char], [[Char]]))
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup [Char]
    inFile Map [Char] (Options, Maybe ([Char], [[Char]]))
    fileOpts of
                                           Nothing        -> do Verbosity -> [Char] -> IO ()
    warn Verbosity
    verbosity ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ "No options found for " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    inFile
                                                                Options -> IO Options
    forall (m :: * -> *) a. Monad m => a -> m a
    return Options
    noOptions
                                           Just (opt :: Options
    opt,gen :: Maybe ([Char], [[Char]])
    gen) -> Options -> IO Options
    forall (m :: * -> *) a. Monad m => a -> m a
    return Options
    opt
                              let search :: [Char]
    search  = [Char] -> [Char]
    dropFileName [Char]
    inFile
                                  options :: Options
    options = Options
    opts { searchPath :: [[Char]]
    searchPath = [Char]
    search [Char] -> [[Char]] -> [[Char]]
    forall a. a -> [a] -> [a]
    : BuildInfo -> [[Char]]
    hsSourceDirs BuildInfo
    build [[Char]] -> [[Char]] -> [[Char]]
    forall a. [a] -> [a] -> [a]
    ++ Options -> [[Char]]
    searchPath Options
    opts
                                                 , outputFiles :: [[Char]]
    outputFiles = [Char]
    outFile [Char] -> [[Char]] -> [[Char]]
    forall a. a -> [a] -> [a]
    : (Options -> [[Char]]
    outputFiles Options
    opts) }
                              (eCode :: ExitCode
    eCode,_) <- [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
    uuagc (Options -> [[Char]]
    optionsToString Options
    options) [Char]
    inFile
                              case ExitCode
    eCode of
                                ExitSuccess   -> [Char] -> Map [Char] (Options, Maybe ([Char], [[Char]])) -> IO ()
    writeFileOptions [Char]
    classesPath ([Char]
    -> (Options, Maybe ([Char], [[Char]]))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    -> Map [Char] (Options, Maybe ([Char], [[Char]]))
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    Map.insert [Char]
    inFile (Options
    opts, ([Char], [[Char]]) -> Maybe ([Char], [[Char]])
    forall a. a -> Maybe a
    Just ([Char]
    outFile, Options -> [[Char]]
    searchPath Options
    options)) Map [Char] (Options, Maybe ([Char], [[Char]]))
    fileOpts)
                                ex :: ExitCode
    ex@(ExitFailure _) -> ExitCode -> IO ()
    forall e a. Exception e => e -> IO a
    throwIO ExitCode
    ex
                    }

    nouuagc :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    nouuagc :: BuildInfo
    -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
    nouuagc build :: BuildInfo
    build lbi :: LocalBuildInfo
    lbi _ =
      PreProcessor :: Bool
    -> (([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ())
    -> PreProcessor
    PreProcessor {
        platformIndependent :: Bool
    platformIndependent = Bool
    True,
        runPreProcessor :: ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
    runPreProcessor = ([Char] -> [Char] -> Verbosity -> IO ())
    -> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
    ([Char] -> [Char] -> Verbosity -> IO ())
    -> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
    mkSimplePreProcessor (([Char] -> [Char] -> Verbosity -> IO ())
     -> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ())
    -> ([Char] -> [Char] -> Verbosity -> IO ())
    -> ([Char], [Char])
    -> ([Char], [Char])
    -> Verbosity
    -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \inFile :: [Char]
    inFile outFile :: [Char]
    outFile verbosity :: Verbosity
    verbosity -> do
          Verbosity -> [Char] -> IO ()
    info Verbosity
    verbosity ("skipping: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    outFile)
      }