    {-# LANGUAGE Safe #-}

    {- arch-tag: Parser for Debian control file
    Copyright (c) 2004-2011 John Goerzen <jgoerzen@complete.org>

    All rights reserved.

    For license and copyright information, see the file LICENSE
    -}

    {- |
       Module     : System.Debian.ControlParser
       Copyright  : Copyright (C) 2004-2011 John Goerzen
       SPDX-License-Identifier: BSD-3-Clause

       Stability  : provisional
       Portability: portable

    This module provides various helpful utilities for dealing with Debian
    files and programs.

    Written by John Goerzen, jgoerzen\@complete.org
    -}

    module System.Debian.ControlParser(control, depPart)
        where

    import           Data.String.Utils             (split)
    import           Text.ParserCombinators.Parsec

    eol, extline :: GenParser Char st String
    eol :: GenParser Char st String
    eol = (GenParser Char st String -> GenParser Char st String
    forall tok st a. GenParser tok st a -> GenParser tok st a
    try (String -> GenParser Char st String
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m String
    string "\r\n"))
          GenParser Char st String
    -> GenParser Char st String -> GenParser Char st String
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> String -> GenParser Char st String
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m String
    string "\n" GenParser Char st String -> String -> GenParser Char st String
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> String -> ParsecT s u m a
    <?> "EOL"

    extline :: GenParser Char st String
    extline = GenParser Char st String -> GenParser Char st String
    forall tok st a. GenParser tok st a -> GenParser tok st a
    try (do Char -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ' '
                      String
    content <- ParsecT String st Identity Char -> GenParser Char st String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (String -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf "\r\n")
                      GenParser Char st String
    forall st. GenParser Char st String
    eol
                      String -> GenParser Char st String
    forall (m :: * -> *) a. Monad m => a -> m a
    return String
    content )

    entry :: GenParser Char st (String, String)
    entry :: GenParser Char st (String, String)
    entry = do String
    key <- ParsecT String st Identity Char
    -> ParsecT String st Identity String
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 (String -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf ":\r\n")
               Char -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ':'
               String
    val <- ParsecT String st Identity Char
    -> ParsecT String st Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (String -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf "\r\n")
               ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
               [String]
    exts <- ParsecT String st Identity String
    -> ParsecT String st Identity [String]
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many ParsecT String st Identity String
    forall st. GenParser Char st String
    extline
               (String, String) -> GenParser Char st (String, String)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String
    key, [String] -> String
    unlines ([String
    val] [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ [String]
    exts))

    {- | Main parser for the control file -}
    control :: CharParser a [(String, String)]
    control :: CharParser a [(String, String)]
    control = do ParsecT String a Identity () -> ParsecT String a Identity [()]
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many ParsecT String a Identity ()
    forall st. GenParser Char st ()
    header
                 [(String, String)]
    retval <- ParsecT String a Identity (String, String)
    -> CharParser a [(String, String)]
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many ParsecT String a Identity (String, String)
    forall st. GenParser Char st (String, String)
    entry
                 [(String, String)] -> CharParser a [(String, String)]
    forall (m :: * -> *) a. Monad m => a -> m a
    return [(String, String)]
    retval

    headerPGP, blankLine, header, headerHash :: GenParser Char st ()
    headerPGP :: GenParser Char st ()
    headerPGP = do String -> ParsecT String st Identity String
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m String
    string "-----BEGIN PGP"
                   ParsecT String st Identity Char
    -> ParsecT String st Identity String
    -> ParsecT String st Identity String
    forall s (m :: * -> *) t u a end.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
    manyTill (String -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf "\r\n") ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
                   () -> GenParser Char st ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    blankLine :: GenParser Char st ()
    blankLine = do ParsecT String st Identity Char
    -> ParsecT String st Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (String -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    oneOf " \t")
                   ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
                   () -> GenParser Char st ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    headerHash :: GenParser Char st ()
    headerHash = do String -> ParsecT String st Identity String
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m String
    string "Hash: "
                    ParsecT String st Identity Char
    -> ParsecT String st Identity String
    -> ParsecT String st Identity String
    forall s (m :: * -> *) t u a end.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
    manyTill (String -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf "\r\n") ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
                    () -> GenParser Char st ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    header :: GenParser Char st ()
    header = (GenParser Char st () -> GenParser Char st ()
    forall tok st a. GenParser tok st a -> GenParser tok st a
    try GenParser Char st ()
    forall st. GenParser Char st ()
    headerPGP) GenParser Char st ()
    -> GenParser Char st () -> GenParser Char st ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> (GenParser Char st () -> GenParser Char st ()
    forall tok st a. GenParser tok st a -> GenParser tok st a
    try GenParser Char st ()
    forall st. GenParser Char st ()
    blankLine) GenParser Char st ()
    -> GenParser Char st () -> GenParser Char st ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> (GenParser Char st () -> GenParser Char st ()
    forall tok st a. GenParser tok st a -> GenParser tok st a
    try GenParser Char st ()
    forall st. GenParser Char st ()
    headerHash)

    {- | Dependency parser.

    Returns (package name, Maybe version, arch list)

    version is (operator, operand) -}
    depPart :: CharParser a (String, (Maybe (String, String)), [String])
    depPart :: CharParser a (String, Maybe (String, String), [String])
    depPart = do String
    packagename <- ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 (String -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf " (")
                 ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ' ')
                 Maybe (String, String)
    version <- (do Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char '('
                                String
    op <- ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 (String -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    oneOf "<>=")
                                ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ' ')
                                String
    vers <- ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 (String -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf ") ")
                                ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ' ')
                                Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ')'
                                Maybe (String, String)
    -> ParsecT String a Identity (Maybe (String, String))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (String, String)
     -> ParsecT String a Identity (Maybe (String, String)))
    -> Maybe (String, String)
    -> ParsecT String a Identity (Maybe (String, String))
    forall a b. (a -> b) -> a -> b
    $ (String, String) -> Maybe (String, String)
    forall a. a -> Maybe a
    Just (String
    op, String
    vers)
                            ) ParsecT String a Identity (Maybe (String, String))
    -> ParsecT String a Identity (Maybe (String, String))
    -> ParsecT String a Identity (Maybe (String, String))
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> Maybe (String, String)
    -> ParsecT String a Identity (Maybe (String, String))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (String, String)
    forall a. Maybe a
    Nothing
                 ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ' ')
                 [String]
    archs <- (do Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char '['
                              String
    t <- ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 (String -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf "]")
                              ParsecT String a Identity Char -> ParsecT String a Identity String
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many (Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ' ')
                              Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ']'
                              [String] -> ParsecT String a Identity [String]
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> String -> [String]
    forall a. Eq a => [a] -> [a] -> [[a]]
    split " " String
    t)
                          ) ParsecT String a Identity [String]
    -> ParsecT String a Identity [String]
    -> ParsecT String a Identity [String]
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> [String] -> ParsecT String a Identity [String]
    forall (m :: * -> *) a. Monad m => a -> m a
    return []
                 (String, Maybe (String, String), [String])
    -> CharParser a (String, Maybe (String, String), [String])
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String
    packagename, Maybe (String, String)
    version, [String]
    archs)