forked from ghc/hsc2hs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Flags.hs
138 lines (113 loc) · 4.78 KB
/
Flags.hs
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
module Flags where
import System.Console.GetOpt
data Mode
= Help
| Version
| UseConfig (ConfigM Maybe)
newtype Id a = Id { fromId :: a }
type Config = ConfigM Id
data ConfigM m = Config {
cmTemplate :: m FilePath,
cmCompiler :: m FilePath,
cmLinker :: m FilePath,
cKeepFiles :: Bool,
cNoCompile :: Bool,
cCrossCompile :: Bool,
cCrossSafe :: Bool,
cVerbose :: Bool,
cFlags :: [Flag]
}
cTemplate :: ConfigM Id -> FilePath
cTemplate c = fromId $ cmTemplate c
cCompiler :: ConfigM Id -> FilePath
cCompiler c = fromId $ cmCompiler c
cLinker :: ConfigM Id -> FilePath
cLinker c = fromId $ cmLinker c
emptyMode :: Mode
emptyMode = UseConfig $ Config {
cmTemplate = Nothing,
cmCompiler = Nothing,
cmLinker = Nothing,
cKeepFiles = False,
cNoCompile = False,
cCrossCompile = False,
cCrossSafe = False,
cVerbose = False,
cFlags = []
}
data Flag
= CompFlag String
| LinkFlag String
| Include String
| Define String (Maybe String)
| Output String
deriving Show
options :: [OptDescr (Mode -> Mode)]
options = [
Option ['o'] ["output"] (ReqArg (addFlag . Output) "FILE")
"name of main output file",
Option ['t'] ["template"] (ReqArg (withConfig . setTemplate) "FILE")
"template file",
Option ['c'] ["cc"] (ReqArg (withConfig . setCompiler) "PROG")
"C compiler to use",
Option ['l'] ["ld"] (ReqArg (withConfig . setLinker) "PROG")
"linker to use",
Option ['C'] ["cflag"] (ReqArg (addFlag . CompFlag) "FLAG")
"flag to pass to the C compiler",
Option ['I'] [] (ReqArg (addFlag . CompFlag . ("-I"++)) "DIR")
"passed to the C compiler",
Option ['L'] ["lflag"] (ReqArg (addFlag . LinkFlag) "FLAG")
"flag to pass to the linker",
Option ['i'] ["include"] (ReqArg (addFlag . include) "FILE")
"as if placed in the source",
Option ['D'] ["define"] (ReqArg (addFlag . define) "NAME[=VALUE]")
"as if placed in the source",
Option [] ["no-compile"] (NoArg (withConfig $ setNoCompile True))
"stop after writing *_hsc_make.c",
Option ['x'] ["cross-compile"] (NoArg (withConfig $ setCrossCompile True))
"activate cross-compilation mode",
Option [] ["cross-safe"] (NoArg (withConfig $ setCrossSafe True))
"restrict .hsc directives to those supported by --cross-compile",
Option ['k'] ["keep-files"] (NoArg (withConfig $ setKeepFiles True))
"do not remove temporary files",
Option ['v'] ["verbose"] (NoArg (withConfig $ setVerbose True))
"dump commands to stderr",
Option ['?'] ["help"] (NoArg (setMode Help))
"display this help and exit",
Option ['V'] ["version"] (NoArg (setMode Version))
"output version information and exit" ]
addFlag :: Flag -> Mode -> Mode
addFlag f (UseConfig c) = UseConfig $ c { cFlags = f : cFlags c }
addFlag _ mode = mode
setMode :: Mode -> Mode -> Mode
setMode Help _ = Help
setMode _ Help = Help
setMode Version _ = Version
setMode (UseConfig {}) _ = error "setMode: UseConfig: Can't happen"
withConfig :: (ConfigM Maybe -> ConfigM Maybe) -> Mode -> Mode
withConfig f (UseConfig c) = UseConfig $ f c
withConfig _ m = m
setTemplate :: FilePath -> ConfigM Maybe -> ConfigM Maybe
setTemplate fp c = c { cmTemplate = Just fp }
setCompiler :: FilePath -> ConfigM Maybe -> ConfigM Maybe
setCompiler fp c = c { cmCompiler = Just fp }
setLinker :: FilePath -> ConfigM Maybe -> ConfigM Maybe
setLinker fp c = c { cmLinker = Just fp }
setKeepFiles :: Bool -> ConfigM Maybe -> ConfigM Maybe
setKeepFiles b c = c { cKeepFiles = b }
setNoCompile :: Bool -> ConfigM Maybe -> ConfigM Maybe
setNoCompile b c = c { cNoCompile = b }
setCrossCompile :: Bool -> ConfigM Maybe -> ConfigM Maybe
setCrossCompile b c = c { cCrossCompile = b }
setCrossSafe :: Bool -> ConfigM Maybe -> ConfigM Maybe
setCrossSafe b c = c { cCrossSafe = b }
setVerbose :: Bool -> ConfigM Maybe -> ConfigM Maybe
setVerbose v c = c { cVerbose = v }
include :: String -> Flag
include s@('\"':_) = Include s
include s@('<' :_) = Include s
include s = Include ("\""++s++"\"")
define :: String -> Flag
define s = case break (== '=') s of
(name, []) -> Define name Nothing
(name, _:value) -> Define name (Just value)