{-# 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 :: 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 :: 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 (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 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 (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
_ <- 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 (m :: * -> *) a. Monad m => a -> m a
return ()
blankLine :: 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 (m :: * -> *) a. Monad m => a -> m a
return ()
headerHash :: 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 (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 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 (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
             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 (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 (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)