    {-# 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 -> ParsecT String st Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    ' '
                      content <- many (noneOf "\r\n")
                      _ <- eol
                      return content )

    entry :: GenParser Char st (String, String)
    entry :: forall st. GenParser Char st (String, String)
    entry = do key <- 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]
    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 ':'
               val <- many (noneOf "\r\n")
               _ <- eol
               exts <- many extline
               return (key, unlines ([val] ++ 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
                 retval <- many entry
                 return retval

    headerPGP, blankLine, header, headerHash :: GenParser Char st ()
    headerPGP :: forall st. 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 String
    "-----BEGIN PGP"
                   _ <- manyTill (noneOf "\r\n") eol
                   return ()
    blankLine :: forall st. 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 String
    " \t")
                   _ <- eol
                   return ()
    headerHash :: forall st. 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 String
    "Hash: "
                    _ <- manyTill (noneOf "\r\n") eol
                    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 packagename <- 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]
    many1 (String -> ParsecT String a Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    String -> ParsecT s u m Char
    noneOf String
    " (")
                 _ <- many (char ' ')
                 version <- (do _ <- char '('
                                op <- many1 (oneOf "<>=")
                                _ <- many (char ' ')
                                vers <- many1 (noneOf ") ")
                                _ <- many (char ' ')
                                _ <- char ')'
                                return $ Just (op, vers)
                            ) <|> return Nothing
                 _ <- many (char ' ')
                 archs <- (do _ <- char '['
                              t <- many1 (noneOf "]")
                              _ <- many (char ' ')
                              _ <- char ']'
                              return (split " " t)
                          ) <|> return []
                 return (packagename, version, archs)