Skip to content
Snippets Groups Projects
sasArg.ml 5.96 KiB
Newer Older
erwan's avatar
erwan committed
(* Time-stamp: <modified the 14/03/2019 (at 17:31) by Erwan Jahier> *)


type t = {
  mutable topo: string;
  mutable length: int;
  mutable verbose: int;
  mutable demon: Demon.t;
erwan's avatar
erwan committed
  mutable seed: int;
  mutable ifi: bool;
  mutable gen_lutin: bool;
  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;
}

erwan's avatar
erwan committed
let usage_msg = ("usage: " ^Sys.argv.(0) ^ " [<option>]* <topology>.dot 
use -h 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;
erwan's avatar
erwan committed
      seed = (Random.self_init (); Random.int 1073741823);
      ifi = false;
      gen_lutin = false;
        _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.Central))
erwan's avatar
erwan committed
      ["Use a Central deamon (which selects exactly one action)"];
    
    mkopt opt  ["--locally-central-demon";"-lcd"]
      (Arg.Unit(fun () -> args.demon <- Demon.LocallyCentral))
erwan's avatar
erwan committed
      ["Use a Locally Central deamon (which never activates two neighbors";
       "actions in the same step)"];
    mkopt opt  ["--distributed-demon";"-dd"]
      (Arg.Unit(fun () -> args.demon <- Demon.Distributed))
erwan's avatar
erwan committed
      ["Use a Distributed deamon (which select at least one action)"];
    
    mkopt opt  ["--custom-demon";"-custd"]
erwan's avatar
erwan committed
      (Arg.Unit(fun () -> args.demon <- Demon.Custom;args.rif <- true))
      ["Use a Custom deamon (forces --rif)"];
   mkopt opt  ["--rif";"-rif"]
      (Arg.Unit(fun () -> args.rif <- true))
      ["Follows RIF conventions"];

erwan's avatar
erwan committed
    mkopt opt  ["--seed";"-seed"]
      (Arg.Int(fun i -> args.seed <- i))
      ["Set the pseudo-random generator seed of build-in demons"];

erwan's avatar
erwan committed
   mkopt opt ~hide:true ["--gen-lutin-demon";"-gld"]
      (Arg.Unit(fun () -> args.gen_lutin <- true))
      ["Generate Lutin demons and exit"];

erwan's avatar
erwan committed
    mkopt opt ~hide:true ["--ignore-first-inputs"; "-ifi"]
      (Arg.Unit(fun () -> args.ifi <- true))
      ["Ignore first inputs (necessary to use luciole via lurette/rdbg/luciole-rif)"];

    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"];

erwan's avatar
erwan committed
    mkopt opt ~hide:true ["--version";"-version";"-v"]
      (Arg.Unit (fun _ ->
           (print_string (SasaVersion.str^"-"^SasaVersion.sha^"\n");flush stdout;exit 0)))
      ["Display the sasa version and exit."];

    mkopt opt ~hide:true ["--ocaml-version"]
erwan's avatar
erwan committed
      (Arg.Unit (fun _ -> (print_string (Sys.ocaml_version^"\n"); 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
)