    {-# 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  : stable
       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 safe Data.List.Utils ( split )
    import safe Text.ParserCombinators.Parsec
        ( char,
          noneOf,
          oneOf,
          string,
          many1,
          manyTill,
          (<?>),
          (<|>),
          many,
          try,
          GenParser,
          CharParser )

    eol, extline :: GenParser Char st String
    eol :: forall st. 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 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 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
    <?> String
    "EOL"

    extline :: forall st. 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
    _ <- Char -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    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 String
    "\r\n")
                      String
    _ <- GenParser Char st String
    forall st. GenParser Char st String
    eol
                      String -> GenParser Char st String
    forall a. a -> ParsecT String st Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return String
    content )

    entry :: GenParser Char st (String, String)
    entry :: forall st. 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 String
    ":\r\n")
               Char
    _ <- Char -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    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 String
    "\r\n")
               String
    _ <- 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 a. a -> ParsecT String st Identity a
    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 :: forall a. 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 a. a -> ParsecT String a Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [(String, String)]
    retval

    headerPGP, blankLine, header, headerHash :: GenParser Char st ()
    headerPGP :: forall st. GenParser Char st ()
    headerPGP = do String
    _ <- String -> ParsecT String st Identity String
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m String
    string String
    "-----BEGIN PGP"
                   String
    _ <- 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 String
    "\r\n") ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
                   () -> GenParser Char st ()
    forall a. a -> ParsecT String st Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    blankLine :: forall st. GenParser Char st ()
    blankLine = do String
    _ <- 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 String
    " \t")
                   String
    _ <- ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
                   () -> GenParser Char st ()
    forall a. a -> ParsecT String st Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    headerHash :: forall st. GenParser Char st ()
    headerHash = do String
    _ <- String -> ParsecT String st Identity String
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m String
    string String
    "Hash: "
                    String
    _ <- 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 String
    "\r\n") ParsecT String st Identity String
    forall st. GenParser Char st String
    eol
                    () -> GenParser Char st ()
    forall a. a -> ParsecT String st Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    header :: forall st. 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 :: forall a. 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 String
    " (")
                 String
    _ <- 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
    ' ')
                 Maybe (String, String)
    version <- (do Char
    _ <- Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    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 String
    "<>=")
                                String
    _ <- 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
    ' ')
                                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 String
    ") ")
                                String
    _ <- 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
    ' ')
                                Char
    _ <- Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    ')'
                                Maybe (String, String)
    -> ParsecT String a Identity (Maybe (String, String))
    forall a. a -> ParsecT String a Identity a
    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 a. a -> ParsecT String a Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (String, String)
    forall a. Maybe a
    Nothing
                 String
    _ <- 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
    ' ')
                 [String]
    archs <- (do Char
    _ <- Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    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 String
    "]")
                              String
    _ <- 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
    ' ')
                              Char
    _ <- Char -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    ']'
                              [String] -> ParsecT String a Identity [String]
    forall a. a -> ParsecT String a Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> String -> [String]
    forall a. Eq a => [a] -> [a] -> [[a]]
    split String
    " " 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 a. a -> ParsecT String a Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return []
                 (String, Maybe (String, String), [String])
    -> CharParser a (String, Maybe (String, String), [String])
    forall a. a -> ParsecT String a Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String
    packagename, Maybe (String, String)
    version, [String]
    archs)