1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE DeriveGeneric #-}
4 module Distribution
.Types
.PkgconfigVersionRange
5 ( PkgconfigVersionRange
(..)
7 , isAnyPkgconfigVersion
8 , withinPkgconfigVersionRange
11 , versionToPkgconfigVersion
12 , versionRangeToPkgconfigVersionRange
15 import Distribution
.Compat
.Prelude
18 import Distribution
.CabalSpecVersion
19 import Distribution
.Parsec
20 import Distribution
.Pretty
21 import Distribution
.Types
.PkgconfigVersion
22 import Distribution
.Types
.Version
23 import Distribution
.Types
.VersionInterval
24 import Distribution
.Types
.VersionRange
26 import qualified Data
.ByteString
.Char8
as BS8
27 import qualified Distribution
.Compat
.CharParsing
as P
28 import qualified Text
.PrettyPrint
as PP
31 data PkgconfigVersionRange
33 | PcThisVersion PkgconfigVersion
-- = version
34 | PcLaterVersion PkgconfigVersion
-- > version (NB. not >=)
35 | PcEarlierVersion PkgconfigVersion
-- < version
36 | PcOrLaterVersion PkgconfigVersion
-- >= version
37 | PcOrEarlierVersion PkgconfigVersion
-- =< version
38 | PcUnionVersionRanges PkgconfigVersionRange PkgconfigVersionRange
39 | PcIntersectVersionRanges PkgconfigVersionRange PkgconfigVersionRange
40 deriving (Generic
, Read, Show, Eq
, Ord
, Typeable
, Data
)
42 instance Binary PkgconfigVersionRange
43 instance Structured PkgconfigVersionRange
44 instance NFData PkgconfigVersionRange
where rnf
= genericRnf
46 instance Pretty PkgconfigVersionRange
where
49 pp
:: Int -> PkgconfigVersionRange
-> PP
.Doc
50 pp _ PcAnyVersion
= PP
.text
"-any"
51 pp _
(PcThisVersion v
) = PP
.text
"==" <<>> pretty v
52 pp _
(PcLaterVersion v
) = PP
.text
">" <<>> pretty v
53 pp _
(PcEarlierVersion v
) = PP
.text
"<" <<>> pretty v
54 pp _
(PcOrLaterVersion v
) = PP
.text
">=" <<>> pretty v
55 pp _
(PcOrEarlierVersion v
) = PP
.text
"<=" <<>> pretty v
56 pp d
(PcUnionVersionRanges v u
) =
58 pp
1 v PP
.<+> PP
.text
"||" PP
.<+> pp
0 u
59 pp d
(PcIntersectVersionRanges v u
) =
61 pp
2 v PP
.<+> PP
.text
"&&" PP
.<+> pp
1 u
63 parens
True = PP
.parens
66 instance Parsec PkgconfigVersionRange
where
67 -- note: the wildcard is used in some places, e.g
68 -- http://hackage.haskell.org/package/bindings-libzip-0.10.1/bindings-libzip.cabal
70 -- however, in the presence of alphanumerics etc. lax version parser,
71 -- wildcard is ill-specified
74 csv
<- askCabalSpecVersion
75 if csv
>= CabalSpecV3_0
77 else versionRangeToPkgconfigVersionRange
<$> versionRangeParser P
.integral csv
79 -- "modern" parser of @pkg-config@ package versions.
80 pkgconfigParser
:: CabalParsing m
=> m PkgconfigVersionRange
81 pkgconfigParser
= P
.spaces
>> expr
83 -- every parser here eats trailing space
85 ts
<- term `P
.sepByNonEmpty`
(P
.string "||" >> P
.spaces
)
86 return $ foldr1 PcUnionVersionRanges ts
89 fs
<- factor `P
.sepByNonEmpty`
(P
.string "&&" >> P
.spaces
)
90 return $ foldr1 PcIntersectVersionRanges fs
92 factor
= parens expr
<|
> prim
95 op
<- P
.munch1 isOpChar P
.<?
> "operator"
97 "-" -> anyPkgconfigVersion
<$ (P
.string "any" *> P
.spaces
)
98 "==" -> afterOp PcThisVersion
99 ">" -> afterOp PcLaterVersion
100 "<" -> afterOp PcEarlierVersion
101 ">=" -> afterOp PcOrLaterVersion
102 "<=" -> afterOp PcOrEarlierVersion
103 _
-> P
.unexpected
$ "Unknown version operator " ++ show op
105 -- https://gitlab.haskell.org/ghc/ghc/issues/17752
121 ((P
.char
'(' P
.<?
> "opening paren") >> P
.spaces
)
122 (P
.char
')' >> P
.spaces
)
124 anyPkgconfigVersion
:: PkgconfigVersionRange
125 anyPkgconfigVersion
= PcAnyVersion
127 -- | TODO: this is not precise, but used only to prettify output.
128 isAnyPkgconfigVersion
:: PkgconfigVersionRange
-> Bool
129 isAnyPkgconfigVersion
= (== PcAnyVersion
)
131 withinPkgconfigVersionRange
:: PkgconfigVersion
-> PkgconfigVersionRange
-> Bool
132 withinPkgconfigVersionRange v
= go
134 go PcAnyVersion
= True
135 go
(PcThisVersion u
) = v
== u
136 go
(PcLaterVersion u
) = v
> u
137 go
(PcEarlierVersion u
) = v
< u
138 go
(PcOrLaterVersion u
) = v
>= u
139 go
(PcOrEarlierVersion u
) = v
<= u
140 go
(PcUnionVersionRanges a b
) = go a || go b
141 go
(PcIntersectVersionRanges a b
) = go a
&& go b
143 -------------------------------------------------------------------------------
145 -------------------------------------------------------------------------------
147 versionToPkgconfigVersion
:: Version
-> PkgconfigVersion
148 versionToPkgconfigVersion
= PkgconfigVersion
. BS8
.pack
. prettyShow
150 versionRangeToPkgconfigVersionRange
:: VersionRange
-> PkgconfigVersionRange
151 versionRangeToPkgconfigVersionRange vr
155 case asVersionIntervals vr
of
156 [] -> PcEarlierVersion
(PkgconfigVersion
(BS8
.pack
"0"))
157 (i
: is
) -> foldl (\r j
-> PcUnionVersionRanges r
(conv j
)) (conv i
) is
159 conv
(VersionInterval
(LowerBound v b
) NoUpperBound
) = convL v b
160 conv
(VersionInterval
(LowerBound v b
) (UpperBound u c
)) = PcIntersectVersionRanges
(convL v b
) (convU u c
)
162 convL v ExclusiveBound
= PcLaterVersion
(versionToPkgconfigVersion v
)
163 convL v InclusiveBound
= PcOrLaterVersion
(versionToPkgconfigVersion v
)
165 convU v ExclusiveBound
= PcEarlierVersion
(versionToPkgconfigVersion v
)
166 convU v InclusiveBound
= PcOrEarlierVersion
(versionToPkgconfigVersion v
)