Commit 3dfc0ea4 authored by Oleg Grenrus's avatar Oleg Grenrus
Browse files

Distribution.SPDX modules

Distribution.SDPX.LicenseId and Distribution.SDPX.LicenceExceptionId are
generated.
parent bf99f8a3
......@@ -230,6 +230,10 @@ library
Distribution.Simple.UHC
Distribution.Simple.UserHooks
Distribution.Simple.Utils
Distribution.SPDX
Distribution.SPDX.LicenseId
Distribution.SPDX.LicenseExceptionId
Distribution.SPDX.LicenseReference
Distribution.System
Distribution.TestSuite
Distribution.Text
......@@ -406,6 +410,7 @@ test-suite unit-tests
UnitTests.Distribution.Compat.Graph
UnitTests.Distribution.Simple.Program.Internal
UnitTests.Distribution.Simple.Utils
UnitTests.Distribution.SPDX
UnitTests.Distribution.System
UnitTests.Distribution.Utils.Generic
UnitTests.Distribution.Utils.NubList
......
......@@ -3,6 +3,7 @@ module Distribution.Parsec.Class (
Parsec(..),
ParsecParser,
simpleParsec,
eitherParsec,
-- * Warnings
parsecWarning,
PWarnType (..),
......@@ -51,6 +52,12 @@ simpleParsec
= either (const Nothing) Just
. P.runParser (lexemeParsec <* P.eof) [] "<simpleParsec>"
-- | Parse a 'String' with 'lexemeParsec'.
eitherParsec :: Parsec a => String -> Either String a
eitherParsec
= either (Left . show) Right
. P.runParser (lexemeParsec <* P.eof) [] "<eitherParsec>"
parsecWarning :: PWarnType -> String -> P.Parsec s [PWarning] ()
parsecWarning t w =
Parsec.modifyState (PWarning t (Position 0 0) w :)
......
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
-- | This module contains a SPDX data from specification version 2.1
--
-- Specification is available on <https://spdx.org/specifications>
module Distribution.SPDX (
-- * License expression
LicenseExpression (..),
simpleLicenseExpression,
OnlyOrAnyLater (..),
-- * License identifier
LicenseId (..),
licenseId,
licenseName,
licenseIsOsiApproved,
mkLicenseId,
-- * License exception
LicenseExceptionId (..),
licenseExceptionId,
licenseExceptionName,
mkLicenseExceptionId,
-- * License reference
LicenseRef,
licenseRef,
licenseDocumentRef,
mkLicenseRef,
mkLicenseRef',
unsafeMkLicenseRef,
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Parsec.Class
import Distribution.Pretty
import Distribution.SPDX.LicenseExceptionId
import Distribution.SPDX.LicenseId
import Distribution.SPDX.LicenseReference
import Distribution.Utils.Generic (isAsciiAlphaNum)
import Text.PrettyPrint ((<+>))
import qualified Distribution.Compat.Parsec as P
import qualified Text.PrettyPrint as Disp
-- | SPDX License Expression.
--
-- @
-- idstring = 1*(ALPHA \/ DIGIT \/ "-" \/ "." )
-- license id = \<short form license identifier inAppendix I.1>
-- license exception id = \<short form license exception identifier inAppendix I.2>
-- license ref = [\"DocumentRef-"1*(idstring)":"]\"LicenseRef-"1*(idstring)
--
-- simple expression = license id \/ license id"+" \/ license ref
--
-- compound expression = 1*1(simple expression \/
-- simple expression \"WITH" license exception id \/
-- compound expression \"AND" compound expression \/
-- compound expression \"OR" compound expression ) \/
-- "(" compound expression ")" )
--
-- license expression = 1*1(simple expression / compound expression)
-- @
data LicenseExpression
= ELicense !(Either LicenseRef LicenseId) !OnlyOrAnyLater !(Maybe LicenseExceptionId)
| EAnd !LicenseExpression !LicenseExpression
| EOr !LicenseExpression !LicenseExpression
deriving (Show, Read, Eq, Typeable, Data, Generic)
simpleLicenseExpression :: LicenseId -> LicenseExpression
simpleLicenseExpression i = ELicense (Right i) Only Nothing
instance Binary LicenseExpression
instance Pretty LicenseExpression where
pretty = go 0
where
go :: Int -> LicenseExpression -> Disp.Doc
go _ (ELicense lic orLater exc) =
let doc = prettyId lic <<>> prettyOrLater orLater
in maybe id (\e d -> d <+> Disp.text "WITH" <+> pretty e) exc doc
go d (EAnd e1 e2) = parens (d < 0) $ go 0 e1 <+> Disp.text "AND" <+> go 0 e2
go d (EOr e1 e2) = parens (d < 1) $ go 1 e1 <+> Disp.text "OR" <+> go 1 e2
prettyId (Right i) = pretty i
prettyId (Left r) = pretty r
prettyOrLater Only = mempty
prettyOrLater OrAnyLater = Disp.char '+'
parens False doc = doc
parens True doc = Disp.parens doc
instance Parsec LicenseExpression where
parsec = expr
where
expr = compoundOr
idstring = P.munch1 $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
-- this parses "simple expression / simple expression "WITH" license exception id"
simple = do
n <- idstring
i <- simple' n
orLater <- P.optionMaybe $ P.char '+'
_ <- P.spaces
exc <- P.optionMaybe $ P.try (P.string "WITH" *> spaces1) *> parsec
return $ ELicense i (maybe Only (const OrAnyLater) orLater) exc
simple' n
| Just l <- "LicenseRef-" `isPrefixOfMaybe` n =
maybe (fail $ "Incorrect LicenseRef format: " ++ n) (return . Left) $ mkLicenseRef Nothing l
| Just d <- "DocumentRef-" `isPrefixOfMaybe` n = do
_ <- P.string ":LicenseRef"
l <- idstring
maybe (fail $ "Incorrect LicenseRef format:" ++ n) (return . Left) $ mkLicenseRef (Just d) l
| otherwise =
maybe (fail $ "Unknown SPDX license identifier: " ++ n) (return . Right) $ mkLicenseId n
-- returns suffix part
isPrefixOfMaybe :: Eq a => [a] -> [a] -> Maybe [a]
isPrefixOfMaybe pfx s
| pfx `isPrefixOf` s = Just (drop (length pfx) s)
| otherwise = Nothing
compoundOr = do
x <- compoundAnd
l <- P.optionMaybe $ P.try (P.string "OR" *> spaces1) *> compoundOr
return $ maybe id (flip EOr) l x
compoundAnd = do
x <- compound
l <- P.optionMaybe $ P.try (P.string "AND" *> spaces1) *> compoundAnd
return $ maybe id (flip EAnd) l x
compound = braces <|> simple
braces = do
_ <- P.char '('
_ <- P.spaces
x <- expr
_ <- P.char ')'
_ <- P.spaces
return x
spaces1 = P.space *> P.spaces
-- notes:
--
-- There MUST NOT be whitespace between a license­id and any following "+".  This supports easy parsing and
-- backwards compatibility.  There MUST be whitespace on either side of the operator "WITH".  There MUST be
-- whitespace and/or parentheses on either side of the operators "AND" and "OR".
--
-- We handle that by having greedy 'idstring' parser, so MITAND would parse as invalid license identifier.
instance NFData LicenseExpression where
rnf (ELicense b i e) = rnf b `seq` rnf i `seq` rnf e
rnf (EAnd x y) = rnf x `seq` rnf y
rnf (EOr x y) = rnf x `seq` rnf y
-------------------------------------------------------------------------------
-- OnlyOrAnyLater
-------------------------------------------------------------------------------
-- | License version range.
data OnlyOrAnyLater = Only | OrAnyLater
deriving (Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data, Generic)
instance NFData OnlyOrAnyLater where
rnf Only = ()
rnf OrAnyLater = ()
instance Binary OnlyOrAnyLater
-- This file is generated. See Makefile's spdx rule
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.SPDX.LicenseExceptionId (
LicenseExceptionId (..),
licenseExceptionId,
licenseExceptionName,
mkLicenseExceptionId,
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Pretty
import Distribution.Parsec.Class
import Distribution.Utils.Generic (isAsciiAlphaNum)
import qualified Distribution.Compat.Map.Strict as Map
import qualified Distribution.Compat.Parsec as P
import qualified Text.PrettyPrint as Disp
-------------------------------------------------------------------------------
-- LicenseExceptionId
-------------------------------------------------------------------------------
-- | SPDX License identifier
data LicenseExceptionId
= DS389_exception -- ^ @389-exception@, 389 Directory Server Exception
| Autoconf_exception_2_0 -- ^ @Autoconf-exception-2.0@, Autoconf exception 2.0
| Autoconf_exception_3_0 -- ^ @Autoconf-exception-3.0@, Autoconf exception 3.0
| Bison_exception_2_2 -- ^ @Bison-exception-2.2@, Bison exception 2.2
| Classpath_exception_2_0 -- ^ @Classpath-exception-2.0@, Classpath exception 2.0
| CLISP_exception_2_0 -- ^ @CLISP-exception-2.0@, CLISP exception 2.0
| DigiRule_FOSS_exception -- ^ @DigiRule-FOSS-exception@, DigiRule FOSS License Exception
| ECos_exception_2_0 -- ^ @eCos-exception-2.0@, eCos exception 2.0
| Fawkes_Runtime_exception -- ^ @Fawkes-Runtime-exception@, Fawkes Runtime Exception
| FLTK_exception -- ^ @FLTK-exception@, FLTK exception
| Font_exception_2_0 -- ^ @Font-exception-2.0@, Font exception 2.0
| Freertos_exception_2_0 -- ^ @freertos-exception-2.0@, FreeRTOS Exception 2.0
| GCC_exception_2_0 -- ^ @GCC-exception-2.0@, GCC Runtime Library exception 2.0
| GCC_exception_3_1 -- ^ @GCC-exception-3.1@, GCC Runtime Library exception 3.1
| Gnu_javamail_exception -- ^ @gnu-javamail-exception@, GNU JavaMail exception
| I2p_gpl_java_exception -- ^ @i2p-gpl-java-exception@, i2p GPL+Java Exception
| Libtool_exception -- ^ @Libtool-exception@, Libtool Exception
| LZMA_exception -- ^ @LZMA-exception@, LZMA exception
| Mif_exception -- ^ @mif-exception@, Macros and Inline Functions Exception
| Nokia_Qt_exception_1_1 -- ^ @Nokia-Qt-exception-1.1@, Nokia Qt LGPL exception 1.1
| OCCT_exception_1_0 -- ^ @OCCT-exception-1.0@, Open CASCADE Exception 1.0
| Openvpn_openssl_exception -- ^ @openvpn-openssl-exception@, OpenVPN OpenSSL Exception
| Qwt_exception_1_0 -- ^ @Qwt-exception-1.0@, Qwt exception 1.0
| U_boot_exception_2_0 -- ^ @u-boot-exception-2.0@, U-Boot exception 2.0
| WxWindows_exception_3_1 -- ^ @WxWindows-exception-3.1@, WxWindows Library Exception 3.1
deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)
instance Binary LicenseExceptionId
instance Pretty LicenseExceptionId where
pretty = Disp.text . licenseExceptionId
instance Parsec LicenseExceptionId where
parsec = do
n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
maybe (fail $ "Unknown SPDX license exception identifier: " ++ n) return $ mkLicenseExceptionId n
instance NFData LicenseExceptionId where
rnf l = l `seq` ()
-------------------------------------------------------------------------------
-- License Data
-------------------------------------------------------------------------------
-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.
licenseExceptionId :: LicenseExceptionId -> String
licenseExceptionId DS389_exception = "389-exception"
licenseExceptionId Autoconf_exception_2_0 = "Autoconf-exception-2.0"
licenseExceptionId Autoconf_exception_3_0 = "Autoconf-exception-3.0"
licenseExceptionId Bison_exception_2_2 = "Bison-exception-2.2"
licenseExceptionId Classpath_exception_2_0 = "Classpath-exception-2.0"
licenseExceptionId CLISP_exception_2_0 = "CLISP-exception-2.0"
licenseExceptionId DigiRule_FOSS_exception = "DigiRule-FOSS-exception"
licenseExceptionId ECos_exception_2_0 = "eCos-exception-2.0"
licenseExceptionId Fawkes_Runtime_exception = "Fawkes-Runtime-exception"
licenseExceptionId FLTK_exception = "FLTK-exception"
licenseExceptionId Font_exception_2_0 = "Font-exception-2.0"
licenseExceptionId Freertos_exception_2_0 = "freertos-exception-2.0"
licenseExceptionId GCC_exception_2_0 = "GCC-exception-2.0"
licenseExceptionId GCC_exception_3_1 = "GCC-exception-3.1"
licenseExceptionId Gnu_javamail_exception = "gnu-javamail-exception"
licenseExceptionId I2p_gpl_java_exception = "i2p-gpl-java-exception"
licenseExceptionId Libtool_exception = "Libtool-exception"
licenseExceptionId LZMA_exception = "LZMA-exception"
licenseExceptionId Mif_exception = "mif-exception"
licenseExceptionId Nokia_Qt_exception_1_1 = "Nokia-Qt-exception-1.1"
licenseExceptionId OCCT_exception_1_0 = "OCCT-exception-1.0"
licenseExceptionId Openvpn_openssl_exception = "openvpn-openssl-exception"
licenseExceptionId Qwt_exception_1_0 = "Qwt-exception-1.0"
licenseExceptionId U_boot_exception_2_0 = "u-boot-exception-2.0"
licenseExceptionId WxWindows_exception_3_1 = "WxWindows-exception-3.1"
-- | License name, e.g. @"GNU General Public License v2.0 only"@
licenseExceptionName :: LicenseExceptionId -> String
licenseExceptionName DS389_exception = "389 Directory Server Exception"
licenseExceptionName Autoconf_exception_2_0 = "Autoconf exception 2.0"
licenseExceptionName Autoconf_exception_3_0 = "Autoconf exception 3.0"
licenseExceptionName Bison_exception_2_2 = "Bison exception 2.2"
licenseExceptionName Classpath_exception_2_0 = "Classpath exception 2.0"
licenseExceptionName CLISP_exception_2_0 = "CLISP exception 2.0 "
licenseExceptionName DigiRule_FOSS_exception = "DigiRule FOSS License Exception"
licenseExceptionName ECos_exception_2_0 = "eCos exception 2.0"
licenseExceptionName Fawkes_Runtime_exception = "Fawkes Runtime Exception "
licenseExceptionName FLTK_exception = "FLTK exception"
licenseExceptionName Font_exception_2_0 = "Font exception 2.0"
licenseExceptionName Freertos_exception_2_0 = "FreeRTOS Exception 2.0"
licenseExceptionName GCC_exception_2_0 = "GCC Runtime Library exception 2.0"
licenseExceptionName GCC_exception_3_1 = "GCC Runtime Library exception 3.1"
licenseExceptionName Gnu_javamail_exception = "GNU JavaMail exception"
licenseExceptionName I2p_gpl_java_exception = "i2p GPL+Java Exception"
licenseExceptionName Libtool_exception = "Libtool Exception"
licenseExceptionName LZMA_exception = "LZMA exception"
licenseExceptionName Mif_exception = "Macros and Inline Functions Exception"
licenseExceptionName Nokia_Qt_exception_1_1 = "Nokia Qt LGPL exception 1.1"
licenseExceptionName OCCT_exception_1_0 = "Open CASCADE Exception 1.0"
licenseExceptionName Openvpn_openssl_exception = "OpenVPN OpenSSL Exception"
licenseExceptionName Qwt_exception_1_0 = "Qwt exception 1.0"
licenseExceptionName U_boot_exception_2_0 = "U-Boot exception 2.0"
licenseExceptionName WxWindows_exception_3_1 = "WxWindows Library Exception 3.1"
-------------------------------------------------------------------------------
-- Creation
-------------------------------------------------------------------------------
-- | Create a 'LicenseExceptionId' from a 'String'.
mkLicenseExceptionId :: String -> Maybe LicenseExceptionId
mkLicenseExceptionId s = Map.lookup s stringLookup
stringLookup :: Map String LicenseExceptionId
stringLookup = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $ [minBound .. maxBound]
This diff is collapsed.
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.SPDX.LicenseReference (
LicenseRef,
licenseRef,
licenseDocumentRef,
mkLicenseRef,
mkLicenseRef',
unsafeMkLicenseRef,
) where
import Prelude ()
import Distribution.Compat.Prelude
import Distribution.Utils.Generic (isAsciiAlphaNum)
import Distribution.Pretty
import Distribution.Parsec.Class
import qualified Distribution.Compat.Parsec as P
import qualified Text.PrettyPrint as Disp
-- | A user defined license reference denoted by @LicenseRef-[idstring]@ (for a license not on the SPDX License List);
data LicenseRef = LicenseRef
{ _lrDocument :: !(Maybe String)
, _lrLicense :: !String
}
deriving (Show, Read, Eq, Typeable, Data, Generic)
-- | License reference.
licenseRef :: LicenseRef -> String
licenseRef = _lrLicense
-- | Document reference.
licenseDocumentRef :: LicenseRef -> Maybe String
licenseDocumentRef = _lrDocument
instance Binary LicenseRef
instance NFData LicenseRef where
rnf (LicenseRef d l) = rnf d `seq` rnf l
instance Pretty LicenseRef where
pretty (LicenseRef Nothing l) = Disp.text "LicenseRef-" <<>> Disp.text l
pretty (LicenseRef (Just d) l) =
Disp.text "DocumentRef-" <<>> Disp.text d <<>> Disp.char ':' <<>> Disp.text "LicenseRef-" <<>> Disp.text l
instance Parsec LicenseRef where
parsec = name <|> doc
where
name = do
_ <- P.string "LicenseRef-"
n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
pure (LicenseRef Nothing n)
doc = do
_ <- P.string "DocumentRef-"
d <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
_ <- P.char ':'
_ <- P.string "LicenseRef-"
n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
pure (LicenseRef (Just d) n)
-- | Create 'LicenseRef' from optional document ref and name.
mkLicenseRef :: Maybe String -> String -> Maybe LicenseRef
mkLicenseRef d l = do
d' <- traverse checkIdString d
l' <- checkIdString l
pure (LicenseRef d' l')
where
checkIdString s
| all (\c -> isAsciiAlphaNum c || c == '-' || c == '.') s = Just s
| otherwise = Nothing
-- | Like 'mkLicenseRef' but convert invalid characters into @-@.
mkLicenseRef' :: Maybe String -> String -> LicenseRef
mkLicenseRef' d l = LicenseRef (fmap f d) (f l)
where
f = map g
g c | isAsciiAlphaNum c || c == '-' || c == '.' = c
| otherwise = '-'
-- | Unsafe 'mkLicenseRef'. Consider using 'mkLicenseRef''.
unsafeMkLicenseRef :: Maybe String -> String -> LicenseRef
unsafeMkLicenseRef d l = case mkLicenseRef d l of
Nothing -> error $ "unsafeMkLicenseRef: panic" ++ show (d, l)
Just x -> x
......@@ -353,7 +353,7 @@ isAsciiAlpha c = ('a' <= c && c <= 'z')
-- False
--
isAsciiAlphaNum :: Char -> Bool
isAsciiAlphaNum c = isAscii c || isDigit c
isAsciiAlphaNum c = isAscii c && isAlphaNum c
unintersperse :: Char -> String -> [String]
unintersperse mark = unfoldr unintersperse1 where
......
......@@ -24,6 +24,7 @@ import qualified UnitTests.Distribution.Utils.Generic
import qualified UnitTests.Distribution.Utils.NubList
import qualified UnitTests.Distribution.Utils.ShortText
import qualified UnitTests.Distribution.Version (versionTests)
import qualified UnitTests.Distribution.SPDX (spdxTests)
tests :: Int -> TestTree
tests mtimeChangeCalibrated =
......@@ -55,6 +56,8 @@ tests mtimeChangeCalibrated =
UnitTests.Distribution.System.tests
, testGroup "Distribution.Version"
UnitTests.Distribution.Version.versionTests
, testGroup "Distribution.SPDX"
UnitTests.Distribution.SPDX.spdxTests
]
extraOptions :: [OptionDescription]
......
{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-deprecations #-}
module UnitTests.Distribution.SPDX (spdxTests) where
import Distribution.Compat.Prelude.Internal
import Prelude ()
import Distribution.SPDX
import Distribution.Parsec.Class (eitherParsec)
import Distribution.Pretty (prettyShow)
import Test.Tasty
import Test.Tasty.QuickCheck
spdxTests :: [TestTree]
spdxTests =
[ testProperty "LicenseId roundtrip" licenseIdRoundtrip
, testProperty "LicenseExceptionId roundtrip" licenseExceptionIdRoundtrip
, testProperty "LicenseExpression roundtrip" licenseExpressionRoundtrip
]
licenseIdRoundtrip :: LicenseId -> Property
licenseIdRoundtrip x =
counterexample (prettyShow x) $
Right x === eitherParsec (prettyShow x)
licenseExceptionIdRoundtrip :: LicenseExceptionId -> Property
licenseExceptionIdRoundtrip x =
counterexample (prettyShow x) $
Right x === eitherParsec (prettyShow x)
licenseExpressionRoundtrip :: LicenseExpression -> Property
licenseExpressionRoundtrip x =
counterexample (prettyShow x) $
Right (reassoc x) === eitherParsec (prettyShow x)
-- Parser produces right biased trees of and/or expressions
reassoc :: LicenseExpression -> LicenseExpression
reassoc (EOr a b) = case reassoc a of
EOr x y -> EOr x (reassoc (EOr y b))
x -> EOr x (reassoc b)
reassoc (EAnd a b) = case reassoc a of
EAnd x y -> EAnd x (reassoc (EAnd y b))
x -> EAnd x (reassoc b)
reassoc l = l
-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------
instance Arbitrary LicenseId where
arbitrary = arbitraryBoundedEnum
instance Arbitrary LicenseExceptionId where
arbitrary = arbitraryBoundedEnum
instance Arbitrary OnlyOrAnyLater where
arbitrary = arbitraryBoundedEnum
instance Arbitrary LicenseExpression where
arbitrary = sized arb
where
arb n
| n <= 0 = simple
| otherwise = oneof
[ simple
, EAnd <$> arbA <*> arbB
, EOr <$> arbA <*> arbB
]
where
m = n `div` 2
arbA = arb m
arbB = arb (n - m)
simple = ELicense <$> (Right <$> arbitrary) <*> arbitrary <*> pure Nothing -- arbitrary
shrink (EAnd a b) = a : b : map (uncurry EAnd) (shrink (a, b))
shrink (EOr a b) = a : b : map (uncurry EOr) (shrink (a, b))
shrink _ = []
.PHONY : all lexer lib exe doctest gen-extra-source-files
.PHONY : all lexer sdpx lib exe doctest gen-extra-source-files
LEXER_HS:=Cabal/Distribution/Parsec/Lexer.hs
SPDX_LICENSE_HS:=Cabal/Distribution/SPDX/LicenseId.hs
SPDX_EXCEPTION_HS:=Cabal/Distribution/SPDX/LicenseExceptionId.hs
all : exe lib
lexer : $(LEXER_HS)
spdx : $(SPDX_LICENSE_HS) $(SPDX_EXCEPTION_HS)
$(LEXER_HS) : boot/Lexer.x
alex --latin1 --ghc -o $@ $^
cat -s $@ > Lexer.tmp
mv Lexer.tmp $@
$(SPDX_LICENSE_HS) : boot/SPDX.LicenseId.template.hs cabal-dev-scripts/src/GenSPDX.hs license-list-data/licenses.json
cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx -- boot/SPDX.LicenseId.template.hs license-list-data/licenses.json $(SPDX_LICENSE_HS)
$(SPDX_EXCEPTION_HS) : boot/SPDX.LicenseExceptionId.template.hs cabal-dev-scripts/src/GenSPDXExc.hs license-list-data/licenses.json
cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx-exc -- boot/SPDX.LicenseExceptionId.template.hs license-list-data/exceptions.json $(SPDX_EXCEPTION_HS)
lib : $(LEXER_HS)
cabal new-build --enable-tests Cabal
exe : $(LEXER_HS)
cabal new-build --enable-tests cabal
cabal new-build --enable-tests cabal-install
doctest :
doctest --fast Cabal/Distribution Cabal/Language
......
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.SPDX.LicenseExceptionId (
LicenseExceptionId (..),
licenseExceptionId,
licenseExceptionName,
mkLicenseExceptionId,
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Pretty
import Distribution.Parsec.Class
import Distribution.Utils.Generic (isAsciiAlphaNum)
import qualified Distribution.Compat.Map.Strict as Map
import qualified Distribution.Compat.Parsec as P
import qualified Text.PrettyPrint as Disp