123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598letversion=Printf.sprintf"%s (\"%s\")\n"(Version.str())Version.shalettool_name="lutin"letusage_msg="usage: "^tool_name^" [options] <file> | "^tool_name^" -help"typegen_mode=Simu|GenLuc|Ocaml|Cstubstypet={mutable_opts:(string*Arg.spec*string)list;(* classical Arg option tab used by Arg.parse *)mutable_user_man:(string*stringlist)list;(* ad hoc tab for pretty prtting usage *)mutable_hidden_man:(string*stringlist)list;(* ad hoc tab for pretty prtting usage *)mutable_test_lex:bool;mutable_test_parse:bool;mutable_test_check:bool;mutable_test_expand:bool;mutable_test_auto:bool;mutable_test_exe:bool;mutable_libs:stringlist;mutable_gen_mode:gen_mode;mutable_step_mode:Lucky.step_mode;mutable_load_mem:bool;mutable_seed:intoption;mutable_reset_seed:bool;mutable_compute_volume:bool;mutable_max_steps:intoption;mutable_show_locals:bool;mutable_see_all_options:bool;mutable_others:stringlist;mutable_margin:int;mutable_infile:stringlist;mutable_main_node:string;mutable_outpipe:bool;mutable_outfile:stringoption;mutable_riffile:stringoption;mutable_only_outputs:bool;mutable_call_gnuplot:bool;mutable_run:bool;mutable_boot:bool;mutable_event_nb:int;}let(make_opt:unit->t)=fun()->{_opts=[];_user_man=[];_hidden_man=[];_test_lex=false;_test_parse=false;_test_check=false;_test_expand=false;_test_auto=false;_test_exe=true;_libs=[];_gen_mode=Simu;_step_mode=Lucky.StepInside;_load_mem=false;_seed=None;_reset_seed=false;_compute_volume=false;_max_steps=None;_show_locals=false;_see_all_options=false;_others=[];_margin=12;_infile=[];_main_node="";_outpipe=false;_outfile=None;_riffile=None;_only_outputs=false;_call_gnuplot=false;_run=true;_boot=false;_event_nb=0;}letset_libsoptlibs={optwith_libs=libs}letlibsopt=matchopt._libswith[]->None|l->Somelletset_precision=Util.change_precision(*******************************************************************************)(* seeds stuff *)letset_seedopts=(matchswith|Somei->Printf.fprintfstderr"The random engine seed is set to %i\n"i;Random.initi;flushstderr;|None->());opt._seed<-sletseed_file_nameopt=Printf.sprintf"%s-%s.seed"(String.concat"-"opt._infile)opt._main_node(* for --replay *)letreset_the_seed_to_lastopt=letf=seed_file_nameoptintryletic=open_infinletseed=int_of_string(input_lineic)inopt._seed<-Someseed;truewith_->Printf.eprintf"W: cannot recover the seed in %s\n"f;flushstderr;falseletrecseedopt=matchopt._seedwith|Somei->i|None->(* No seed is set:
- in -replay mode, we first try to read the seed in the seed file
- otherwise, we create a random seed and save if into opt, and
into a file for -replay *)ifopt._reset_seed&&reset_the_seed_to_lastoptthen(seedopt)elseletseed=Random.self_init();Random.int1073741823inletseed_file=seed_file_nameoptinletoc=open_outseed_fileinPrintf.fprintfoc"%d\n%s\n"seed(Util.entete"#""");flushoc;close_outoc;opt._seed<-Someseed;seed(* Emulate the event number when not run under rdbg so that we are able
to tell at which event we reached a deadlock
*)(* let event_nb = ref 0 *)letevent_incropt=opt._event_nb<-opt._event_nb+1;()let(get_event_nb:t->int)=funopt->opt._event_nb(* all unrecognized options are accumulated *)let(add_other:t->string->unit)=funopts->opt._others<-s::opt._othersletinfileopt=opt._infilelettest_lexopt=opt._test_lexlettest_parseopt=opt._test_parselettest_checkopt=opt._test_checklettest_expandopt=opt._test_expandlettest_autoopt=opt._test_autoletmain_nodeopt=opt._main_nodelettest_exeopt=opt._test_exeletmax_stepsopt=opt._max_stepsletgen_modeopt=opt._gen_modeletload_memopt=opt._load_memletoutfileopt=opt._outfileletoutpipeopt=opt._outpipeletriffileopt=opt._riffileletcall_gnuplotopt=opt._call_gnuplotletonly_outputsopt=opt._only_outputsletshow_localsopt=opt._show_localsletset_show_localsoptb=opt._show_locals<-bletsee_all_optionsopt=opt._see_all_optionsletstep_modeopt=opt._step_modeletset_step_modeoptsm=opt._step_mode<-smletcompute_volumeopt=opt._compute_volumeletset_compute_volumeoptb=opt._compute_volume<-bletrunopt=opt._runletbootopt=opt._bootletpspecosopt(c,ml)=(let(m1,oth)=matchmlwith|h::t->(h,t)|_->("",[])inlett2=String.makeopt._margin' 'inletcl=String.lengthcinlett1=if(cl<opt._margin)thenString.make(opt._margin-cl)' 'else"\n"^t2inPrintf.fprintfos"%s%s%s"ct1m1;List.iter(functionx->Printf.fprintfos"\n%s%s"t2x)oth;Printf.fprintfos"\n";)letusageosopt=(letl=List.revopt._user_maninPrintf.fprintfos"%s\n\n"usage_msg;List.iter(pspecosopt)l)lethelpopt()=(usagestdoutopt;exit0)letfull_usageosopt=(Printf.fprintfos"%s\n"usage_msg;letl=List.rev(opt._hidden_man)inList.iter(pspecosopt)l)letfull_helpopt()=(full_usagestdoutopt;exit0)letunexpectedsopt=(prerr_string("unexpected argument \""^s^"\"");prerr_newline();usagestderropt;exit1)letfile_notfoundfopt=(prerr_string("File not found: \""^f^"\"");prerr_newline();usagestderropt;exit1)letdebug_options_list=["CkType";"Expand";"LutExe";"Run";"LutProg";"LucProg";"AutoGen";"AutoExplore";"Guard"]let(mkopt:t->stringlist->?hide:bool->?arg:string->Arg.spec->stringlist->unit)=funoptol?(hide=false)?(arg="")seml->lettretoo=opt._opts<-(o,se,"")::opt._optsinList.itertretool;letcol1=(String.concat", "ol)^arginifhidethenopt._hidden_man<-(col1,ml)::opt._hidden_manelseopt._user_man<-(col1,ml)::opt._user_man(*
let tabs = String.make (col - (String.length o) - (String.length arg)) ' ' in
(* (o, se, arg^tabs^m) *)
(o, se, arg^"\n "^m)
*)(*** USER OPTIONS TAB **)let(mkoptab:t->unit)=funopt->(mkoptopt["-n";"-m";"-node";"-main"]~arg:" <string>"(Arg.String(functions->Luc2c.option.Luc2c.main_node<-s;opt._main_node<-s))["Set the main node"];mkoptopt~hide:true["-check"](Arg.Unit(function_->opt._run<-false))["check the program is correct and exit"];mkoptopt["--version";"-version"](Arg.Unit(function_->print_stringversion;flushstdout;exit0))["Print the current version and exit"];mkoptopt~hide:true["--ocaml-version"](Arg.Unit(fun()->print_string(Sys.ocaml_version);flushstdout;exit0))["Print the current ocaml version it was compiled with and exit"];(* verbose *)mkoptopt["-v"](Arg.Unit(function_->Verbose.on()))["Set the verbose level to 1"];mkoptopt["-vl"]~arg:" <int>"(Arg.Int(functioni->Verbose.seti))["Set the verbose level"];(* ---- COMPILE OPTIONS: broken...*)(* mkopt opt *)(* ["-luc"] *)(* (Arg.Unit(function _ -> opt._gen_mode <- GenLuc ; ())) *)(* ["Generate a lucky program"] *)(* ; *)(* mkopt opt (* XXX Merge it with -luc !!! *) *)(* ["-o"] *)(* ~arg:" <string>" *)(* (Arg.String(function s -> opt._outfile <- Some s)) *)(* ["with -luc: write to specified file (default is infile_main.luc)"] *)(* ; *)(* mkopt opt *)(* ["-os"] *)(* (Arg.Unit(function s -> opt._outpipe <- true)) *)(* ["write to stdout"] *)(* ; *)mkoptopt["-gnuplot";"-gp"](Arg.Unit(function_s->opt._call_gnuplot<-true;(matchopt._riffilewith|None->opt._riffile<-Some"_lutin.rif"|Some_->())))["call gnuplot-rif to display data (type 'a' in the gnuplot window to refresh it)."];mkoptopt["-rif";"-quiet";"-q";"-only-outputs"](Arg.Unit(function_s->opt._only_outputs<-true))["display only outputs on stdout (i.e., behave as a rif input file)"];mkoptopt["-o"]~arg:" <string>"(Arg.String(functions->opt._outfile<-Somes;(*let news = if not (Sys.file_exists s) *)(* then s else *)(* let rec find_free_name b i = *)(* let f = Printf.sprintf "%s-%d.rif" b i in *)(* if Sys.file_exists f then *)(* find_free_name b (i+1) *)(* else *)(* f *)(* in *)(* find_free_name (Filename.chop_extension s) 1 *)(* in *)if(Filename.check_suffixs".rif")then(opt._riffile<-Somes;Luc2c.option.Luc2c.rif<-Somes)))["output file name"];mkoptopt["-L";"-lib"]~arg:" <string>"(Arg.String(functions->opt._libs<-s::opt._libs))["Add a dynamic library where external code will be searched in"];(* ---- SIMU/SOLVER OPTIONS *)(* simu *)mkoptopt["--replay";"-r"](Arg.Unit(fun()->opt._reset_seed<-true))["Use the last generated seed to replay the last run"];mkoptopt["-seed"]~arg:" <int>"(Arg.Int(functioni->opt._seed<-Somei;()))["Set a seed for the pseudo-random generator (wins over --replay)"];mkoptopt["-boot"](Arg.Unit(function_->opt._boot<-true))["Perform ther first step without reading inputs"];mkoptopt["--max-steps";"-l"]~arg:" <int>"(Arg.Int(functioni->opt._max_steps<-Somei;()))["Set a maximum number of simulation steps to perform"];mkoptopt["--step-inside";"-si"](Arg.Unit(function_->opt._step_mode<-Lucky.StepInside))["Draw inside the convex hull of solutions (default)"];mkoptopt["--step-edges";"-se"](Arg.Unit(function_->opt._step_mode<-Lucky.StepEdges))(* "draw inside the convex hull of solutions, but a little bit more at edges and vertices" *)["Draw a little bit more at edges and vertices"];mkoptopt["--step-vertices";"-sv"](Arg.Unit(function_->opt._step_mode<-Lucky.StepVertices))["Draw among the vertices of the convex hull of solutions"];mkoptopt~hide:true["-fair";"--compute-poly-volume"](Arg.Unit(fun()->opt._compute_volume<-true;))["[Currently not supported anymore; if you need it, please ask] ";"Compute polyhedron volume before drawing";"More fair, but more expensive"];mkoptopt["-precision";"-p"](Arg.Int(funi->Util.change_precisioni))~arg:" <int>"["Set the precision used for converting float to rational (default: "^(string_of_int!Util.precision)^")"];mkoptopt["-locals";"-loc"](Arg.Unit(fun()->opt._show_locals<-true))["Show local variables in the generated data."];mkoptopt["--ocaml";"-ocaml"](Arg.Unit(function_s->opt._gen_mode<-Ocaml))["Generate ocaml glue code that makes it possible to call the lutin interpreter ";"from ocaml with the current set of arguments."];(* ---- luc2c OPTIONS *)mkoptopt~hide:true["--2c-4c"](Arg.Unit(fun()->opt._gen_mode<-Cstubs;Luc2c.option.Luc2c.gen_mode<-Luc2c.Nop))["Generate C code to be called from C "];mkoptopt~hide:true["--2c-4c-socks"]~arg:" <string> (the machine IP)"(Arg.String(functionstr->opt._gen_mode<-Cstubs;Luc2c.option.Luc2c.use_sockets<-true;Luc2c.option.Luc2c.sock_addr<-str))["The same as --2c-4c, but using sockets."];mkoptopt~hide:true["---sock-port";"-port"]~arg:" <int> "(Arg.Int(functioni->Luc2c.option.Luc2c.sock_port<-i))["to set the port number; meaningful only if --2c-4c-socks is used."];mkoptopt~hide:true["--2c-4lustre"]~arg:" <string>"(Arg.String(funstr->opt._gen_mode<-Cstubs;Luc2c.option.Luc2c.gen_mode<-Luc2c.Lustre;Luc2c.option.Luc2c.calling_module_name<-str))["Generate C code to be called from Lustre V4 "];mkoptopt~hide:true["--2c-4scade"]~arg:" <string>"(Arg.String(funstr->opt._gen_mode<-Cstubs;Luc2c.option.Luc2c.gen_mode<-Luc2c.Scade;Luc2c.option.Luc2c.calling_module_name<-str))["Generate C code to be called from Scade "];mkoptopt~hide:true["-luciole";"--2c-4luciole"](Arg.Unit(fun_->opt._gen_mode<-Cstubs;Luc2c.option.Luc2c.gen_mode<-Luc2c.Luciole))["not working anymore: use luciole-rif instead."];mkoptopt~hide:true["--2c-4alice"]~arg:" <string>"(Arg.String(funstr->opt._gen_mode<-Cstubs;Luc2c.option.Luc2c.gen_mode<-Luc2c.Alices;Luc2c.option.Luc2c.calling_module_name<-str))["Generate C and C++ code to be called from Alice"];mkoptopt~hide:true["--2c-output-dir"]~arg:" <string>"(Arg.String(funstr->Luc2c.option.Luc2c.output_dir<-str))["Set the directory where C files are generated"];mkoptopt["-h";"-help";"--help"](Arg.Unit(helpopt))["Display this message"];(* to show Hidden opt *)mkoptopt["-more"](* (Arg.Unit(fun _ -> opt._see_all_options <- true)) *)(Arg.Unit(full_helpopt))["Show hidden options (for dev purposes)"];(* HIDDEN *)(* test lexical *)mkoptopt~hide:true["-tlex"](Arg.Unit(function_->opt._gen_mode<-GenLuc;opt._test_lex<-true;()))["Test the lexical analysis"];(* test syntaxique *)mkoptopt~hide:true["-tparse"](Arg.Unit(function_->opt._gen_mode<-GenLuc;opt._test_parse<-true;()))["Test the syntactic analysis"];(* test type-checking *)mkoptopt~hide:true["-tcheck"](Arg.Unit(function_->opt._gen_mode<-GenLuc;opt._test_check<-true;()))["Test the type/binding checking"];(* test expansion *)mkoptopt~hide:true["-texpand"](Arg.Unit(function_->opt._gen_mode<-GenLuc;opt._test_expand<-true;()))["Test the expansion"];(* test autogen *)mkoptopt~hide:true["-tauto"](Arg.Unit(function_->opt._gen_mode<-GenLuc;opt._test_auto<-true;()))["Test the automaton generation"];(* use ths old algo (ie, not the LutExe based simu *)mkoptopt~hide:true["-old"](Arg.Unit(function_->opt._gen_mode<-Simu;opt._test_exe<-false;()))["Simulation with an old algo."];(* paranoid/debug *)mkoptopt~hide:true["-paranoid"](Arg.Unit(function_->Utils.set_paranoid()))["Set on the paranoid mode (slower)"];mkoptopt~hide:true["-prof"](Arg.Unit(function_->Utils.set_prof()))["Set on the profile mode"];(* misc degub flag *)mkoptopt~hide:true["-debug";"-dbg"](Arg.Symbol(debug_options_list,(functions->letx=Verbose.get_flagsinVerbose.set_flagx)))["<dbg_flag>";"Possible dbg_flag are: "^(String.concat", "debug_options_list)])letfirst_lineb=(try(letf=String.indexb'\n'inString.subb0f)withNot_found->b)letcurrent=ref0;;(* La ``méthode'' principale *)letparseargv=(letopt=make_opt()inletsave_current=!currentintry(mkoptabopt;Arg.parse_argv~current:currentargvopt._opts(add_otheropt)usage_msg;(List.iter(funf->iff=""then()elseif(String.subf01="-")thenunexpectedfoptelseifnot(Sys.file_existsf)thenfile_notfoundfoptelse())opt._others);opt._infile<-(List.revopt._others);current:=save_current;opt)with(* only 1rst line is interesting ! *)|Arg.Badmsg->Printf.fprintfstderr"%s\n"(first_linemsg);usagestderropt;exit2;|Arg.Helpmsg->Printf.fprintfstderr"%s\n"(first_linemsg);helpopt();)