    module General.Makefile(parseMakefile) where

    import qualified Data.ByteString.Char8 as BS
    import Data.Char

    endsSlash :: BS.ByteString -> Bool
    endsSlash :: ByteString -> Bool
    endsSlash = ByteString -> ByteString -> Bool
    BS.isSuffixOf (Char -> ByteString
    BS.singleton Char
    '\\')

    wordsMakefile :: BS.ByteString -> [BS.ByteString]
    wordsMakefile :: ByteString -> [ByteString]
    wordsMakefile = [ByteString] -> [ByteString]
    f ([ByteString] -> [ByteString])
    -> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> ByteString -> [ByteString]
    BS.splitWith Char -> Bool
    isSpace
        where
            f :: [ByteString] -> [ByteString]
    f (ByteString
    x:[ByteString]
    xs) | ByteString -> Bool
    BS.null ByteString
    x = [ByteString] -> [ByteString]
    f [ByteString]
    xs
            f (ByteString
    x:ByteString
    y:[ByteString]
    xs) | ByteString -> Bool
    endsSlash ByteString
    x = [ByteString] -> [ByteString]
    f ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
    forall a b. (a -> b) -> a -> b
    $ [ByteString] -> ByteString
    BS.concat [HasCallStack => ByteString -> ByteString
    ByteString -> ByteString
    BS.init ByteString
    x, Char -> ByteString
    BS.singleton Char
    ' ', ByteString
    y] ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : [ByteString]
    xs
            f (ByteString
    x:[ByteString]
    xs) = ByteString
    x ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : [ByteString] -> [ByteString]
    f [ByteString]
    xs
            f [] = []

    parseMakefile :: BS.ByteString -> [(BS.ByteString, [BS.ByteString])]
    parseMakefile :: ByteString -> [(ByteString, [ByteString])]
    parseMakefile = (ByteString -> [(ByteString, [ByteString])])
    -> [ByteString] -> [(ByteString, [ByteString])]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ByteString -> [(ByteString, [ByteString])]
    f ([ByteString] -> [(ByteString, [ByteString])])
    -> (ByteString -> [ByteString])
    -> ByteString
    -> [(ByteString, [ByteString])]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [ByteString]
    join ([ByteString] -> [ByteString])
    -> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> [ByteString]
    linesCR
        where
            join :: [ByteString] -> [ByteString]
    join [ByteString]
    xs = case (ByteString -> Bool)
    -> [ByteString] -> ([ByteString], [ByteString])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span ByteString -> Bool
    endsSlash [ByteString]
    xs of
                ([], []) -> []
                ([ByteString]
    xs, []) -> [[ByteString] -> ByteString
    BS.unwords ([ByteString] -> ByteString) -> [ByteString] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> ByteString) -> [ByteString] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map HasCallStack => ByteString -> ByteString
    ByteString -> ByteString
    BS.init [ByteString]
    xs]
                ([], ByteString
    y:[ByteString]
    ys) -> ByteString
    y ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : [ByteString] -> [ByteString]
    join [ByteString]
    ys
                ([ByteString]
    xs, ByteString
    y:[ByteString]
    ys) -> [ByteString] -> ByteString
    BS.unwords ((ByteString -> ByteString) -> [ByteString] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map HasCallStack => ByteString -> ByteString
    ByteString -> ByteString
    BS.init [ByteString]
    xs [ByteString] -> [ByteString] -> [ByteString]
    forall a. [a] -> [a] -> [a]
    ++ [ByteString
    y]) ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : [ByteString] -> [ByteString]
    join [ByteString]
    ys

            f :: ByteString -> [(ByteString, [ByteString])]
    f ByteString
    x = [(ByteString
    a, ByteString -> [ByteString]
    wordsMakefile (ByteString -> [ByteString]) -> ByteString -> [ByteString]
    forall a b. (a -> b) -> a -> b
    $ Int -> ByteString -> ByteString
    BS.drop Int
    1 ByteString
    b) | ByteString
    a <- ByteString -> [ByteString]
    wordsMakefile ByteString
    a]
                where (ByteString
    a,ByteString
    b) = (Char -> Bool) -> ByteString -> (ByteString, ByteString)
    BS.break (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ':') (ByteString -> (ByteString, ByteString))
    -> ByteString -> (ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ (Char -> Bool) -> ByteString -> ByteString
    BS.takeWhile (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Char
    '#') ByteString
    x

    -- | This is a hot-spot, so optimised
    linesCR :: BS.ByteString -> [BS.ByteString]
    linesCR :: ByteString -> [ByteString]
    linesCR ByteString
    x = case Char -> ByteString -> [ByteString]
    BS.split Char
    '\n' ByteString
    x of
        ByteString
    x:[ByteString]
    xs | Just (Char
    '\r',ByteString
    x) <- ByteString -> Maybe (Char, ByteString)
    unsnoc ByteString
    x -> ByteString
    x ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : (ByteString -> ByteString) -> [ByteString] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ByteString
    x -> case ByteString -> Maybe (Char, ByteString)
    unsnoc ByteString
    x of Just (Char
    '\r',ByteString
    x) -> ByteString
    x; Maybe (Char, ByteString)
    _ -> ByteString
    x) [ByteString]
    xs
        [ByteString]
    xs -> [ByteString]
    xs
        where
            -- the ByteString unsnoc was introduced in a newer version
            unsnoc :: ByteString -> Maybe (Char, ByteString)
    unsnoc ByteString
    x | ByteString -> Bool
    BS.null ByteString
    x = Maybe (Char, ByteString)
    forall a. Maybe a
    Nothing
                     | Bool
    otherwise = (Char, ByteString) -> Maybe (Char, ByteString)
    forall a. a -> Maybe a
    Just (ByteString -> Char
    BS.last ByteString
    x, HasCallStack => ByteString -> ByteString
    ByteString -> ByteString
    BS.init ByteString
    x)