diff --git a/bin/sasArg.ml b/bin/sasArg.ml new file mode 100644 index 0000000000000000000000000000000000000000..eae36008a6cdb515bd467057e7ed5452a53cc6d2 --- /dev/null +++ b/bin/sasArg.ml @@ -0,0 +1,176 @@ +(* Time-stamp: <modified the 07/03/2019 (at 10:35) by Erwan> *) + + +type t = { + mutable topo: string; + mutable length: int; + mutable verbose: int; + mutable demon: Demon.t; + + mutable _args : (string * Arg.spec * string) list; + mutable _user_man : (string * string list) list; + mutable _hidden_man: (string * string list) list; + + mutable _others : string list; + mutable _margin : int; +} + +let usage_msg = ("usage: " ^Sys.argv.(0) ^ " [<option>] [<topology>.dot file] +use --help to see the available options. +" ) +let print_usage () = Printf.printf "%s\n" usage_msg; flush stdout + + +let (make_args : unit -> t) = + fun () -> + { + topo = ""; + length = 100; + verbose = 0; + demon = Demon.Distributed; + _args = []; + _user_man = []; + _hidden_man = []; + _others = []; + _margin =12; + } + +let (args : t) = make_args () + +let pspec os (c, ml) = ( + let (m1, oth) = match ml with + | h::t -> (h,t) + | _ -> ("",[]) + in + let t2 = String.make args._margin ' ' in + let cl = String.length c in + let t1 = if (cl < args._margin ) then + String.make (args._margin - cl) ' ' + else + "\n"^t2 + in + Printf.fprintf os "%s%s%s" c t1 m1; + List.iter (function x -> Printf.fprintf os "\n%s%s" t2 x) oth ; + Printf.fprintf os "\n" ; +) + +let options oc = ( + let l = List.rev args._user_man in + List.iter (pspec oc) l +) +let more_options oc = ( + let l = List.rev (args._hidden_man) in + List.iter (pspec oc) l +) +let (mkopt : t -> string list -> ?hide:bool -> ?arg:string -> Arg.spec -> + string list -> unit) = + fun opt ol ?(hide=false) ?(arg="") se ml -> + let treto o = opt._args <- (o, se, "")::opt._args in + List.iter treto ol ; + let col1 = (String.concat ", " ol)^arg in + if hide + then opt._hidden_man <- (col1, ml)::opt._hidden_man + else opt._user_man <- (col1, ml)::opt._user_man + +let myexit i = exit i + +(*** User Options Tab **) +let (mkoptab : t -> unit) = + fun opt -> + let _nl = "\n"^(String.make args._margin ' ') in + ( + mkopt opt ["--synchronous-demon";"-sd"] + (Arg.Unit(fun () -> args.demon <- Demon.Synchronous)) + ["Use a Synchronous deamon"]; + + mkopt opt ["--central-demon";"-cd"] + (Arg.Unit(fun () -> args.demon <- Demon.Synchronous)) + ["Use a Central deamon (selects exactly one action)"]; + + mkopt opt ["--locally-central-demon";"-lcd"] + (Arg.Unit(fun () -> args.demon <- Demon.Synchronous)) + ["Use a Locally Central deamon (never activates two neighbor"; + "actions in the same step)"]; + mkopt opt ["--distributed-demon";"-dd"] + (Arg.Unit(fun () -> args.demon <- Demon.Synchronous)) + ["Use a Distributed deamon (select at least one action)"]; + + mkopt opt ["--custom-demon";"-custd"] + (Arg.Unit(fun () -> args.demon <- Demon.Synchronous)) + ["Use a Custom deamon"]; + + mkopt opt ["--length";"-l"] ~arg:" <int>" + (Arg.Int (fun i -> args.length <- i)) + ["Maximum number of steps to be done (" ^ (string_of_int args.length) ^ " by default).\n"]; + + mkopt opt ~hide:true ["--ocaml-version"] + (Arg.Unit (fun _ -> (print_string (Sys.ocaml_version) ; flush stdout; exit 0))) + ["Display the version ocaml version sasa was compiled with and exit."]; + + mkopt opt ["--verbose";"-vl"] ~arg:" <int>" + (Arg.Int (fun i -> args.verbose <- i)) ["Set the verbose level"]; + + mkopt opt ["--help";"-help"; "-h"] + (Arg.Unit (fun _ -> print_usage();options stdout; exit 0)) + ["Display main options"]; + + mkopt opt ["--more";"-m"] (Arg.Unit (fun () -> more_options stdout; exit 0)) + ["Display more options"] + + ) + +(* all unrecognized options are accumulated *) +let (add_other : t -> string -> unit) = + fun opt s -> + opt._others <- s::opt._others + +let current = ref 0;; +let first_line b = ( + try ( + let f = String.index b '\n' in + String.sub b 0 f + ) with Not_found -> b +) +let file_notfound f = ( + prerr_string ("File not found: \""^f^"\""); + prerr_newline (); + myexit 1 +) +let unexpected s = ( + prerr_string ("unexpected argument \""^s^"\""); + prerr_newline (); + myexit 1 +) + +let parse argv = ( + let save_current = !current in + try ( + mkoptab args; + Arg.parse_argv ~current:current argv args._args (add_other args) usage_msg; + (List.iter + (fun f -> + if (String.sub f 0 1 = "-") then + unexpected f + else if not (Sys.file_exists f) then + file_notfound f + else () + ) + args._others); + current := save_current; + args.topo <- (match args._others with + [] -> + Printf.fprintf stderr "*** The topology file is missing in '%s'\n%s\n" + (Sys.argv.(0)) usage_msg; + exit 2; + | x::_ -> x + ) + ) + with + (* only 1rst line is interesting ! *) + | Arg.Bad msg -> + Printf.fprintf stderr "*** Error when calling '%s': %s\n%s\n" (Sys.argv.(0)) + (first_line msg) usage_msg; exit 2; + | Arg.Help msg -> + Printf.fprintf stdout "%s\n%s\n" msg usage_msg; + options stdout; exit 0 +) diff --git a/bin/sasa.ml b/bin/sasa.ml index 7e9f14a83884c98dd451a1365a2ee59861c6a901..4743e27efdb72d802460b4a5780ff9f4b5f81ada 100644 --- a/bin/sasa.ml +++ b/bin/sasa.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 07/03/2019 (at 09:43) by Erwan> *) +(* Time-stamp: <modified the 07/03/2019 (at 10:29) by Erwan> *) (* XXX Je pourrais utiliser Lwt pour rendre step non-bloquant, ce qui permettrait d'accelerer la simu sur les machines qui ont plusieurs @@ -63,7 +63,8 @@ let (update_env: Env.t -> Process.t * Algo.local_env -> Env.t) = p.variables open Process - +open SasArg + let (to_algo_neighbor: Env.t -> Topology.neighbor -> Algo.neighbor) = fun e n -> { @@ -86,7 +87,7 @@ let rec (simu: int -> int -> Process.t list -> [] pl_n in assert (all <> []); - let al = Demon.f Demon.Distributed all in + let al = Demon.f args.demon all in (* Do the steps *) let lenv_list = @@ -109,12 +110,25 @@ let rec (simu: int -> int -> Process.t list -> | _ -> if i > 0 then simu n (i-1) pl pl_n ne else () let () = - let dot_file = Sys.argv.(1) in + ( try SasArg.parse Sys.argv; + with + Failure(e) -> + output_string stdout e; + flush stdout ; + exit 2 + | e -> + output_string stdout (Printexc.to_string e); + flush stdout; + exit 2 + ); + + + let dot_file = SasArg.args.topo in let nl = Topology.read dot_file in let nstrl = List.map (fun n -> n.Topology.id) nl in let nstr = String.concat "," nstrl in try - Algo.verbose_level :=1; + Algo.verbose_level := SasArg.args.verbose; Random.self_init(); Printf.printf "nodes: %s\nedges:\n" nstr; let e = Env.init () in @@ -123,6 +137,6 @@ let () = let neighors = List.map get_neighors pl in let pl_n = List.combine pl neighors in List.iter dump_process pl_n; - let n = (int_of_string Sys.argv.(2)) in + let n = SasArg.args.length in simu n n pl pl_n e with Dynlink.Error e -> Printf.printf "E: %s\n"(Dynlink.error_message e) diff --git a/test/dijkstra-ring/Makefile b/test/dijkstra-ring/Makefile index b0baebca1089a15fc2c157ccb1c3a5b9b0688b09..39eb0379c47bbe94f9a38e8719dbf72974069e39 100644 --- a/test/dijkstra-ring/Makefile +++ b/test/dijkstra-ring/Makefile @@ -13,7 +13,7 @@ MLI=-I $(DIR)/lib/algo ocamlopt -shared $(MLI) $^ -o $@ test: ring.cmxs ringroot.cmxs - $(sasa) ring.dot 150 + $(sasa) ring.dot clean: rm -f *.cmxs sasa *.cmi *.o *.cmx *.pdf