isabelle-hacks/fxp/src/Apps/Esis/esisOptions.sml

117 lines
4.4 KiB
Standard ML

signature EsisOptions =
sig
val O_SILENT : bool ref
val O_ERROR_DEVICE : TextIO.outstream ref
val O_ERROR_LINEWIDTH : int ref
val O_OUTPUT_FILE : string ref
val O_NON_DIRECT : UniChar.Char ref
val setEsisDefaults : unit -> unit
val setEsisOptions : Options.Option list * (string -> unit)
-> bool * bool * string option * string option
val esisUsage : Options.Usage
end
structure EsisOptions : EsisOptions =
struct
open Options
val O_SILENT = ref false
val O_ERROR_DEVICE = ref TextIO.stdErr
val O_ERROR_LINEWIDTH = ref 80
val O_OUTPUT_FILE = ref "-"
val O_NON_DIRECT = ref (0wx100 : UniChar.Char)
fun setEsisDefaults () =
let
val _ = O_SILENT := false
val _ = O_ERROR_DEVICE := TextIO.stdErr
val _ = O_OUTPUT_FILE := "-"
val _ = O_NON_DIRECT := 0wx100
in ()
end
val esisUsage =
[U_ITEM(["-o <file>","--output=<file>"],"Write output to file (stdout)"),
U_ITEM(["-s","--silent"],"Suppress reporting of errors and warnings"),
U_ITEM(["-e <file>","--error-output=<file>"],"Redirect errors to file (stderr)"),
U_SEP,
U_ITEM(["-7","--ascii"],"Produce output in ASCII (7 bit) encoding"),
U_ITEM(["-8","--latin1"],"Produce output in LATIN1 (8 bit) encoding (default)"),
U_SEP,
U_ITEM(["--version"],"Print the version number and exit"),
U_ITEM(["-?","--help"],"Print this text and exit"),
U_ITEM(["--"],"Do not recognize remaining arguments as options")
]
fun setEsisOptions (opts,optError) =
let
fun onlyOne what = "at most one "^what^" may be specified"
fun unknown pre opt = String.concat ["unknown option ",pre,opt]
fun hasNoArg pre key = String.concat ["option ",pre,key," expects no argument"]
fun mustHave pre key = String.concat ["option ",pre,key," must have an argument"]
fun check_noarg(key,valOpt) =
if isSome valOpt then optError (hasNoArg "--" key) else ()
fun do_long (pars as (v,h,e,f)) (key,valOpt) =
case key
of "help" => (v,true,e,f) before check_noarg(key,valOpt)
| "version" => (true,h,e,f) before check_noarg(key,valOpt)
| "silent" => pars before O_SILENT := true before check_noarg(key,valOpt)
| "ascii" => pars before O_NON_DIRECT := 0wx80 before check_noarg(key,valOpt)
| "latin1" => pars before O_NON_DIRECT := 0wx100 before check_noarg(key,valOpt)
| "output" =>
(case valOpt
of NONE => pars before optError (mustHave "--" key)
| SOME s => pars before O_OUTPUT_FILE := s)
| "error-output" =>
(case valOpt
of NONE => pars before optError (mustHave "--" key)
| SOME s => (v,h,SOME s,f))
| _ => pars before optError(unknown "--" key)
fun do_short (pars as (v,h,e,f)) (cs,opts) =
case cs
of nil => doit pars opts
| [#"o"] => (case opts
of OPT_STRING s::opts1 => (O_OUTPUT_FILE := s;
doit pars opts1)
| _ => (optError (mustHave "-" "o"); doit pars opts))
| [#"e"] => (case opts
of OPT_STRING s::opts1 => doit (v,h,SOME s,f) opts1
| _ => (optError (mustHave "-" "e"); doit pars opts))
| cs => doit (foldr
(fn (c,pars)
=> case c
of #"s" => pars before O_SILENT := true
| #"7" => pars before O_NON_DIRECT := 0wx80
| #"8" => pars before O_NON_DIRECT := 0wx100
| #"o" => pars before optError (mustHave "-" "o")
| #"e" => pars before optError (mustHave "-" "e")
| #"?" => (v,true,e,f)
| c => pars before
optError(unknown "-" (String.implode [c])))
pars cs) opts
and doit pars nil = pars
| doit (pars as (v,h,e,f)) (opt::opts) =
case opt
of OPT_LONG(key,valOpt) => doit (do_long pars (key,valOpt)) opts
| OPT_SHORT cs => do_short pars (cs,opts)
| OPT_STRING s => if isSome f
then let val _ = optError(onlyOne "input file")
in doit pars opts
end
else doit (v,h,e,SOME s) opts
| OPT_NOOPT => doit pars opts
| OPT_NEG cs => let val _ = if null cs then ()
else app (fn c => optError
(unknown "-n" (String.implode[c]))) cs
in doit pars opts
end
in doit (false,false,NONE,NONE) opts
end
end