2020-03-23 22:43:06 +04:00
|
|
|
(* Parsing command-line options *)
|
|
|
|
|
|
|
|
(* The type [options] gathers the command-line options. *)
|
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
module SSet = Set.Make (String)
|
2020-03-23 22:43:06 +04:00
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
type line_comment = string (* Opening of a line comment *)
|
|
|
|
type block_comment = <opening : string; closing : string>
|
2020-04-03 21:06:35 +04:00
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
let mk_block ~opening ~closing : block_comment =
|
|
|
|
object
|
|
|
|
method opening = opening
|
|
|
|
method closing = closing
|
|
|
|
end
|
2020-03-26 19:51:08 +04:00
|
|
|
|
2020-03-23 22:43:06 +04:00
|
|
|
type options = <
|
2020-03-31 21:44:10 +04:00
|
|
|
input : string option;
|
2020-03-23 22:43:06 +04:00
|
|
|
libs : string list;
|
2020-03-31 21:44:10 +04:00
|
|
|
verbose : SSet.t;
|
2020-03-26 19:51:08 +04:00
|
|
|
offsets : bool;
|
2020-04-24 22:54:13 +04:00
|
|
|
block : block_comment option;
|
|
|
|
line : line_comment option;
|
|
|
|
ext : string
|
2020-03-23 22:43:06 +04:00
|
|
|
>
|
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
let make ~input ~libs ?block ?line ~offsets ~verbose ~ext : options =
|
2020-03-23 22:43:06 +04:00
|
|
|
object
|
|
|
|
method input = input
|
|
|
|
method libs = libs
|
2020-04-24 22:54:13 +04:00
|
|
|
method block = block
|
|
|
|
method line = line
|
2020-03-23 22:43:06 +04:00
|
|
|
method offsets = offsets
|
2020-03-26 19:51:08 +04:00
|
|
|
method verbose = verbose
|
2020-03-31 21:44:10 +04:00
|
|
|
method ext = ext
|
2020-03-23 22:43:06 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
(* Auxiliary functions and modules *)
|
|
|
|
|
|
|
|
let printf = Printf.printf
|
|
|
|
let sprintf = Printf.sprintf
|
|
|
|
let print = print_endline
|
|
|
|
|
|
|
|
(* Printing a string in red to standard error *)
|
|
|
|
|
|
|
|
let highlight msg = Printf.eprintf "\027[31m%s\027[0m%!" msg
|
|
|
|
|
|
|
|
(* Failure *)
|
|
|
|
|
|
|
|
let abort msg =
|
|
|
|
highlight (sprintf "Command-line error: %s\n" msg); exit 1
|
|
|
|
|
|
|
|
(* Help *)
|
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
let help ext () =
|
2020-03-23 22:43:06 +04:00
|
|
|
let file = Filename.basename Sys.argv.(0) in
|
2020-03-31 21:44:10 +04:00
|
|
|
printf "Usage: %s [<option> ...] [<input>%s | \"-\"]\n" file ext;
|
2020-04-24 22:54:13 +04:00
|
|
|
printf "where <input>%s is the LIGO source file (default: stdin),\n" ext;
|
2020-03-23 22:43:06 +04:00
|
|
|
print "and each <option> (if any) is one of the following:";
|
2020-03-25 21:52:23 +04:00
|
|
|
print " -I <paths> Inclusion paths (colon-separated)";
|
2020-03-26 19:51:08 +04:00
|
|
|
print " --columns Columns for source locations";
|
|
|
|
print " --verbose=<stages> preproc";
|
|
|
|
print " -h, --help This help";
|
2020-03-23 22:43:06 +04:00
|
|
|
exit 0
|
|
|
|
|
|
|
|
(* Specifying the command-line options a la GNU *)
|
|
|
|
|
|
|
|
let input = ref None
|
|
|
|
and libs = ref []
|
|
|
|
and columns = ref false
|
2020-03-26 19:51:08 +04:00
|
|
|
and verbose = ref SSet.empty
|
|
|
|
and verb_str = ref ""
|
2020-03-23 22:43:06 +04:00
|
|
|
|
|
|
|
let split_at_colon = Str.(split (regexp ":"))
|
|
|
|
|
|
|
|
let add_path p = libs := !libs @ split_at_colon p
|
|
|
|
|
2020-03-26 19:51:08 +04:00
|
|
|
let add_verbose d =
|
|
|
|
verbose := List.fold_left (fun x y -> SSet.add y x)
|
|
|
|
!verbose
|
|
|
|
(split_at_colon d)
|
2020-04-24 22:54:13 +04:00
|
|
|
let specs ext =
|
|
|
|
let open! Getopt in [
|
2020-03-23 22:43:06 +04:00
|
|
|
'I', nolong, None, Some add_path;
|
2020-04-24 22:54:13 +04:00
|
|
|
'h', "help", Some (help ext), None;
|
2020-03-26 19:51:08 +04:00
|
|
|
noshort, "columns", set columns true, None;
|
|
|
|
noshort, "verbose", None, Some add_verbose
|
2020-03-23 22:43:06 +04:00
|
|
|
]
|
|
|
|
|
|
|
|
(* Handler of anonymous arguments *)
|
|
|
|
|
|
|
|
let anonymous arg =
|
|
|
|
match !input with
|
2020-03-31 21:44:10 +04:00
|
|
|
None -> input := Some arg
|
|
|
|
| Some _ -> abort (sprintf "Multiple inputs")
|
2020-03-23 22:43:06 +04:00
|
|
|
|
|
|
|
(* Checking options and exporting them as non-mutable values *)
|
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
let check ?block ?line ~ext =
|
2020-03-23 22:43:06 +04:00
|
|
|
let libs = !libs
|
|
|
|
|
|
|
|
and offsets = not !columns
|
|
|
|
|
2020-03-26 19:51:08 +04:00
|
|
|
and verbose = !verbose
|
|
|
|
|
2020-03-23 22:43:06 +04:00
|
|
|
and input =
|
|
|
|
match !input with
|
2020-04-09 18:18:26 +04:00
|
|
|
None | Some "-" -> None
|
2020-03-31 21:44:10 +04:00
|
|
|
| Some file_path ->
|
|
|
|
if Filename.check_suffix file_path ext
|
|
|
|
then if Sys.file_exists file_path
|
|
|
|
then Some file_path
|
|
|
|
else abort "Source file not found."
|
|
|
|
else abort ("Source file lacks the extension " ^ ext ^ ".")
|
2020-03-23 22:43:06 +04:00
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
in make ~input ~libs ?block ?line ~offsets ~verbose ~ext
|
2020-03-23 22:43:06 +04:00
|
|
|
|
|
|
|
(* Parsing the command-line options *)
|
|
|
|
|
2020-04-24 22:54:13 +04:00
|
|
|
type extension = string
|
|
|
|
|
|
|
|
let read ?block ?line (ext: extension) =
|
2020-03-23 22:43:06 +04:00
|
|
|
try
|
2020-04-24 22:54:13 +04:00
|
|
|
Getopt.parse_cmdline (specs ext) anonymous;
|
2020-03-26 19:51:08 +04:00
|
|
|
(verb_str :=
|
|
|
|
let apply e a =
|
|
|
|
if a = "" then e else sprintf "%s, %s" e a
|
|
|
|
in SSet.fold apply !verbose "");
|
2020-04-24 22:54:13 +04:00
|
|
|
check ?block ?line ~ext
|
2020-03-23 22:43:06 +04:00
|
|
|
with Getopt.Error msg -> abort msg
|