131 lines
4.3 KiB
OCaml
131 lines
4.3 KiB
OCaml
(**************************************************************************)
|
|
(* *)
|
|
(* OCaml *)
|
|
(* *)
|
|
(* Pierre Chambart, OCamlPro *)
|
|
(* Mark Shinwell and Leo White, Jane Street Europe *)
|
|
(* *)
|
|
(* Copyright 2015--2016 OCamlPro SAS *)
|
|
(* Copyright 2015--2016 Jane Street Group LLC *)
|
|
(* *)
|
|
(* All rights reserved. This file is distributed under the terms of *)
|
|
(* the GNU Lesser General Public License version 2.1, with the *)
|
|
(* special exception on linking described in the file LICENSE. *)
|
|
(* *)
|
|
(**************************************************************************)
|
|
|
|
let fatal err =
|
|
prerr_endline err;
|
|
exit 2
|
|
|
|
module Make (S : sig
|
|
module Key : sig
|
|
type t
|
|
val of_string : string -> t
|
|
module Map : Map.S with type key = t
|
|
end
|
|
|
|
module Value : sig
|
|
type t
|
|
val of_string : string -> t
|
|
end
|
|
end) = struct
|
|
type parsed = {
|
|
base_default : S.Value.t;
|
|
base_override : S.Value.t S.Key.Map.t;
|
|
user_default : S.Value.t option;
|
|
user_override : S.Value.t S.Key.Map.t;
|
|
}
|
|
|
|
let default v =
|
|
{ base_default = v;
|
|
base_override = S.Key.Map.empty;
|
|
user_default = None;
|
|
user_override = S.Key.Map.empty; }
|
|
|
|
let set_base_default value t =
|
|
{ t with base_default = value }
|
|
|
|
let add_base_override key value t =
|
|
{ t with base_override = S.Key.Map.add key value t.base_override }
|
|
|
|
let reset_base_overrides t =
|
|
{ t with base_override = S.Key.Map.empty }
|
|
|
|
let set_user_default value t =
|
|
{ t with user_default = Some value }
|
|
|
|
let add_user_override key value t =
|
|
{ t with user_override = S.Key.Map.add key value t.user_override }
|
|
|
|
let no_equals value =
|
|
match String.index value '=' with
|
|
| exception Not_found -> true
|
|
| _index -> false
|
|
|
|
exception Parse_failure of exn
|
|
|
|
let parse_exn str ~update =
|
|
let values = Misc.Stdlib.String.split str ~on:',' in
|
|
let parsed =
|
|
List.fold_left (fun acc value ->
|
|
match String.index value '=' with
|
|
| exception Not_found ->
|
|
begin match S.Value.of_string value with
|
|
| value -> set_user_default value acc
|
|
| exception exn -> raise (Parse_failure exn)
|
|
end
|
|
| equals ->
|
|
let key_value_pair = value in
|
|
let length = String.length key_value_pair in
|
|
assert (equals >= 0 && equals < length);
|
|
if equals = 0 then begin
|
|
raise (Parse_failure (
|
|
Failure "Missing key in argument specification"))
|
|
end;
|
|
let key =
|
|
let key = String.sub key_value_pair 0 equals in
|
|
try S.Key.of_string key
|
|
with exn -> raise (Parse_failure exn)
|
|
in
|
|
let value =
|
|
let value =
|
|
String.sub key_value_pair (equals + 1) (length - equals - 1)
|
|
in
|
|
try S.Value.of_string value
|
|
with exn -> raise (Parse_failure exn)
|
|
in
|
|
add_user_override key value acc)
|
|
!update
|
|
values
|
|
in
|
|
update := parsed
|
|
|
|
let parse str ~help_text ~update =
|
|
match parse_exn str ~update with
|
|
| () -> ()
|
|
| exception (Parse_failure exn) ->
|
|
fatal (Printf.sprintf "%s: %s" (Printexc.to_string exn) help_text)
|
|
|
|
type parse_result =
|
|
| Ok
|
|
| Parse_failed of exn
|
|
|
|
let parse_no_error str ~update =
|
|
match parse_exn str ~update with
|
|
| () -> Ok
|
|
| exception (Parse_failure exn) -> Parse_failed exn
|
|
|
|
let get ~key parsed =
|
|
match S.Key.Map.find key parsed.user_override with
|
|
| value -> value
|
|
| exception Not_found ->
|
|
match parsed.user_default with
|
|
| Some value -> value
|
|
| None ->
|
|
match S.Key.Map.find key parsed.base_override with
|
|
| value -> value
|
|
| exception Not_found -> parsed.base_default
|
|
|
|
end
|