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
|
functor Driver(E: EMIT): DRIVER = struct
structure I = E.I
structure P = E.I.P
datatype execMode = Normal | DebugE | DebugT
type config = {
file: string option,
includeDirs: string list,
mode: execMode
}
val updateC = fn z =>
let
fun from file includeDirs mode = { file, includeDirs, mode }
fun to f { file, includeDirs, mode } = f file includeDirs mode
in
FRU.makeUpdate3 (from, from, to)
end z
val initConfig: config = { file = NONE, includeDirs = [], mode = Normal }
val die = fn z => die 1 z
fun finish ({ file = NONE, ... }: config) = die `"No file specified" %
| finish conf = updateC conf u#includeDirs rev %
fun parseFlag conf "-dE" tail =
parseCmdArgs (updateC conf s#mode DebugE %) tail
| parseFlag conf "-dT" tail =
parseCmdArgs (updateC conf s#mode DebugT %) tail
| parseFlag _ arg _ = die `arg `": unknown flag" %
and parseCmdArgs conf [] = finish conf
| parseCmdArgs _ ("-I" :: []) =
die `"-I: expected directory path after flag" %
| parseCmdArgs conf ("-I" :: path :: tail) =
parseCmdArgs (updateC conf u#includeDirs
(fn dirs => path :: dirs) %) tail
| parseCmdArgs (C as { file, ... }) (arg :: tail) =
if String.sub (arg, 0) = #"-" then
parseFlag C arg tail
else
case file of
NONE =>
let
val size = size arg
in
if String.extract (arg, size - 2, NONE) <> ".c" then
die `arg `": expected file with .c suffix" %
else
let
val file = String.substring (arg, 0, size - 2)
in
parseCmdArgs (updateC C s#file (SOME file) %) tail
end
end
| SOME _ => die `arg `": file already specified" %
fun exec () =
let
val config = parseCmdArgs initConfig (CommandLine.arguments ())
val file = valOf $ #file config
in
case (#mode config) of
Normal =>
let
val parseCtx = P.createCtx file (#includeDirs config) true
fun collect ctx =
let
val (continue, ctx) = P.parseDef ctx
in
if continue then
collect ctx
else
P.finalize ctx
end
val parseCtx = collect parseCtx
val progInfo = P.explode parseCtx
val ilCtx = I.createCtx progInfo (SOME $ file ^ ".i")
in
E.emit (file ^ ".s") ilCtx (SOME $ file ^ ".e")
end
| DebugT => P.P.T.debugPrint file
| DebugE => P.P.debugPrint file (#includeDirs config)
end
end
|