File: Options.hs

package info (click to toggle)
cpphs 1.18.5-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 812 kB
  • ctags: 21
  • sloc: haskell: 1,707; sh: 120; makefile: 49; ansic: 11
file content (156 lines) | stat: -rwxr-xr-x 5,868 bytes parent folder | download
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 []                 = []