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