1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
-----------------------------------------------------------------------------
-- |
-- Module : Options
-- Copyright : 2006 Malcolm Wallace
-- Licence : LGPL
--
-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
-- Stability : experimental
-- Portability : All
--
-- This module deals with Cpphs options and parsing them
-----------------------------------------------------------------------------
module Language.Preprocessor.Cpphs.Options
( CpphsOptions(..)
, BoolOptions(..)
, parseOptions
, defaultCpphsOptions
, defaultBoolOptions
, trailing
) where
import Data.Maybe
import Data.List (isPrefixOf)
-- | Cpphs options structure.
data CpphsOptions = CpphsOptions
{ infiles :: [FilePath]
, outfiles :: [FilePath]
, defines :: [(String,String)]
, includes :: [String]
, preInclude:: [FilePath] -- ^ Files to \#include before anything else
, boolopts :: BoolOptions
} deriving (Show)
-- | Default options.
defaultCpphsOptions :: CpphsOptions
defaultCpphsOptions = CpphsOptions { infiles = [], outfiles = []
, defines = [], includes = []
, preInclude = []
, boolopts = defaultBoolOptions }
-- | Options representable as Booleans.
data BoolOptions = BoolOptions
{ macros :: Bool -- ^ Leave \#define and \#undef in output of ifdef?
, locations :: Bool -- ^ Place \#line droppings in output?
, hashline :: Bool -- ^ Write \#line or {-\# LINE \#-} ?
, pragma :: Bool -- ^ Keep \#pragma in final output?
, stripEol :: Bool -- ^ Remove C eol (\/\/) comments everywhere?
, stripC89 :: Bool -- ^ Remove C inline (\/**\/) comments everywhere?
, lang :: Bool -- ^ Lex input as Haskell code?
, ansi :: Bool -- ^ Permit stringise \# and catenate \#\# operators?
, layout :: Bool -- ^ Retain newlines in macro expansions?
, literate :: Bool -- ^ Remove literate markup?
, warnings :: Bool -- ^ Issue warnings?
} deriving (Show)
-- | Default settings of boolean options.
defaultBoolOptions :: BoolOptions
defaultBoolOptions = BoolOptions { macros = True, locations = True
, hashline = True, pragma = False
, stripEol = False, stripC89 = False
, lang = True, ansi = False
, layout = False, literate = False
, warnings = True }
-- | Raw command-line options. This is an internal intermediate data
-- structure, used during option parsing only.
data RawOption
= NoMacro
| NoLine
| LinePragma
| Pragma
| Text
| Strip
| StripEol
| Ansi
| Layout
| Unlit
| SuppressWarnings
| Macro (String,String)
| Path String
| PreInclude FilePath
| IgnoredForCompatibility
deriving (Eq, Show)
flags :: [(String, RawOption)]
flags = [ ("--nomacro", NoMacro)
, ("--noline", NoLine)
, ("--linepragma", LinePragma)
, ("--pragma", Pragma)
, ("--text", Text)
, ("--strip", Strip)
, ("--strip-eol", StripEol)
, ("--hashes", Ansi)
, ("--layout", Layout)
, ("--unlit", Unlit)
, ("--nowarn", SuppressWarnings)
]
-- | Parse a single raw command-line option. Parse failure is indicated by
-- result Nothing.
rawOption :: String -> Maybe RawOption
rawOption x | isJust a = a
where a = lookup x flags
rawOption ('-':'D':xs) = Just $ Macro (s, if null d then "1" else tail d)
where (s,d) = break (=='=') xs
rawOption ('-':'U':xs) = Just $ IgnoredForCompatibility
rawOption ('-':'I':xs) = Just $ Path $ trailing "/\\" xs
rawOption xs | "--include="`isPrefixOf`xs
= Just $ PreInclude (drop 10 xs)
rawOption _ = Nothing
-- | Trim trailing elements of the second list that match any from
-- the first list. Typically used to remove trailing forward\/back
-- slashes from a directory path.
trailing :: (Eq a) => [a] -> [a] -> [a]
trailing xs = reverse . dropWhile (`elem`xs) . reverse
-- | Convert a list of RawOption to a BoolOptions structure.
boolOpts :: [RawOption] -> BoolOptions
boolOpts opts =
BoolOptions
{ macros = not (NoMacro `elem` opts)
, locations = not (NoLine `elem` opts)
, hashline = not (LinePragma `elem` opts)
, pragma = Pragma `elem` opts
, stripEol = StripEol`elem` opts
, stripC89 = StripEol`elem` opts || Strip `elem` opts
, lang = not (Text `elem` opts)
, ansi = Ansi `elem` opts
, layout = Layout `elem` opts
, literate = Unlit `elem` opts
, warnings = not (SuppressWarnings `elem` opts)
}
-- | Parse all command-line options.
parseOptions :: [String] -> Either String CpphsOptions
parseOptions xs = f ([], [], []) xs
where
f (opts, ins, outs) (('-':'O':x):xs) = f (opts, ins, x:outs) xs
f (opts, ins, outs) (x@('-':_):xs) = case rawOption x of
Nothing -> Left x
Just a -> f (a:opts, ins, outs) xs
f (opts, ins, outs) (x:xs) = f (opts, normalise x:ins, outs) xs
f (opts, ins, outs) [] =
Right CpphsOptions { infiles = reverse ins
, outfiles = reverse outs
, defines = [ x | Macro x <- reverse opts ]
, includes = [ x | Path x <- reverse opts ]
, preInclude=[ x | PreInclude x <- reverse opts ]
, boolopts = boolOpts opts
}
normalise ('/':'/':filepath) = normalise ('/':filepath)
normalise (x:filepath) = x:normalise filepath
normalise [] = []
|