Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file options.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2019 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(** Management of command-line options *)openMopsa_utilsopenArgExtmoduleStringSet=SetExt.StringSet(** Command-line option *)typeopt=|O_builtinofarg(** Built-in option *)|O_languageofstring*arg(** Language option *)|O_domainofstring*arg(** Domain option *)|O_sharedofstring*arg(** Shared options that can be imported by several domains. *)(** {2 Registration} *)(** **************** *)(** List of registered options *)letoptions:optlistref=ref[](** Map giving the shared options imported by a domain *)letimports:(string(* domain *),StringSet.t(* imported options *))Hashtbl.t=Hashtbl.create16(** Register a built-in option *)letregister_builtin_option(arg:arg)=options:=(O_builtinarg)::!options(** Register a language option. *)letregister_language_option(lang:string)(arg:arg)=options:=(O_language(lang,arg))::!options(** Register a domain option. *)letregister_domain_option(dom:string)(arg:arg)=options:=(O_domain(dom,arg))::!options(** Register a shared option *)letregister_shared_option(name:string)(arg:arg)=options:=(O_shared(name,arg))::!options(** Import a shared option into a domain *)letimport_shared_option(name:string)(domain:string)=letold=tryHashtbl.findimportsdomainwithNot_found->StringSet.emptyinHashtbl.replaceimportsdomain(StringSet.addnameold)(** Get the imported options of a domain. *)letfind_domain_imports(dom:string)=tryHashtbl.findimportsdomwithNot_found->StringSet.empty(** {2 Interface with Arg and Output} *)(** ********************************* *)letopt_to_argopt=matchoptwith|O_builtind|O_language(_,d)|O_domain(_,d)|O_shared(_,d)->d(** {2 Bash completion capabilities} *)(*************************************)let()=letcompleteargs=(* let () = Format.eprintf "@.complete |%a| {%s} %s@." (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "|") Format.pp_print_string) args (OptionExt.default "" (OptionExt.lift (fun s -> s ^ "/config/") (Sys.getenv_opt "SHAREDIR"))) in *)letr=ArgExt.complete_argv~prefer_getopt_long:trueargs(List.map(funo->leta=opt_to_argoina.key,a.spec,a.doc)!options)ArgExt.emptyin(* let () = Format.eprintf "-> |%a|@." (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "|") Format.pp_print_string) args in *)r|>List.iterprint_endline;exit0inletcomplete_arg:arg={key="--complete";doc="Bash completion helper";category="Configuration";default="";spec=Rest_all(complete,ArgExt.empty_all)}inregister_builtin_optioncomplete_arg(** {2 Filters} *)(** *********** *)(** Return the list of options *)letget_options()=List.mapopt_to_arg!options(** Return the list of built-in options *)letget_builtin_options()=List.filter(funopt->matchoptwith|O_builtin_->true|_->false)!options|>List.mapopt_to_arg(** Return the list of registered options of a language *)letget_language_options(lang:string)=List.filter(funopt->matchoptwith|O_language(l,arg)->l=lang|_->false)!options|>List.mapopt_to_arg(** Find a standalone option *)letfind_shared_option(name:string)=List.find(funopt->matchoptwith|O_shared(n,_)->n=name|_->false)!options(** Return the list of registered options of a domain *)letget_domain_options(dom:string)=(* Options registered by the domain *)letopt1=List.filter(funopt->matchoptwith|O_domain(d,arg)->d=dom|_->false)!optionsin(* Options registered by the groups of the domain *)letopt2=find_domain_importsdom|>StringSet.elements|>List.mapfind_shared_optioninList.mapopt_to_arg(opt1@opt2)(** {2 Built-in options} *)(** ******************** *)(** Path to share directory *)let()=register_builtin_option{key="-share-dir";category="Configuration";doc=" path to the share directory";spec=Set_string(Paths.opt_share_dir,empty);default=OptionExt.default""(Sys.getenv_opt"SHAREDIR");}(** Analysis configuration *)let()=register_builtin_option{key="-config";category="Configuration";doc=" path to the configuration file to use for the analysis";spec=Set_string(Config.Parser.opt_config,funargs->if!Config.Parser.opt_config<>""thenletconfig_path=Filename.dirname(Paths.resolve_config_file!Config.Parser.opt_config)inletlang=Filename.basenameconfig_pathinArgExt.complete_files_in_dir~prefix:langconfig_pathargselseemptyargs);default="";}(** Warnings *)let()=register_builtin_option{key="-no-warning";category="Debugging";doc=" deactivate warning messages";spec=ClearDebug.print_warnings;default="";}(** Active hooks *)let()=register_builtin_option{key="-hook";category="Configuration";doc=" activate a hook";spec=String((funs->tryCore.Hook.activate_hookswithNot_found->Exceptions.panic"hook %s not found"s),funargs->letd=List.map(fun(h:(moduleCore.Hook.HOOK))->letmoduleH=(valh)inH.name)(Core.Hook.list_hooks())inArgExt.strings(List.sort_uniqcompared)args);default="";}(** Size of the cache *)let()=register_builtin_option{key="-cache";category="Configuration";doc=" size of the analysis cache";spec=Set_int(Core.Cache.opt_cache,strings["1";"5";"10"]);default="5";}(** Debug channels *)(* Activate "print" channel by default *)let()=Debug.parse"print"let()=register_builtin_option{key="-debug";category="Debugging";doc=" select active debug channels. (syntax: <c1>,<c2>,...,<cn> and '_' can be used as a wildcard)";spec=String((funs->(* Always keep "print" channel *)Debug.parse("print,"^s)),empty(* FIXME BASH *));default="print";};register_builtin_option{key="-no-color";category="Debugging";doc=" deactivate colors in debug messages.";spec=ClearDebug.print_color;default="";}(** List of available domains *)let()=register_builtin_option{key="-list";category="Help";doc=" list available domains/checks/hooks; if a configuration is specified, only used domains are listed";spec=Symbol(["domains";"checks";"hooks";"reductions"],(funselection->let()=matchselectionwith|"domains"->letdomains=if!Config.Parser.opt_config=""thenConfig.Parser.all_domains()elsePaths.resolve_config_file!Config.Parser.opt_config|>Config.Parser.domainsinList.sort_uniqcomparedomains|>Output.Factory.list_domains|"reductions"->letreductions=Config.Parser.all_reductions()inList.sort_uniqcomparereductions|>Output.Factory.list_reductions|"checks"->letchecks=if!Config.Parser.opt_config=""then(* List checks of all registered domains *)letdomains=Config.Parser.all_domains()inList.fold_left(funaccdomain->tryletmoduleD=(valSig.Abstraction.Stacked.find_stacked_domaindomain)inD.checks@accwithNot_found->tryletmoduleD=(valSig.Abstraction.Domain.find_standard_domaindomain)inD.checks@accwithNot_found->tryletmoduleD=(valSig.Abstraction.Stateless.find_stateless_domaindomain)inD.checks@accwithNot_found->acc)[]domainselseletabstraction=Config.Parser.(parse@@Paths.resolve_config_file!opt_config)inletdomain=Config.Builder.from_jsonabstraction.domaininletmoduleDomain=(valdomain)inDomain.checksinList.sort_uniqcomparechecks|>Output.Factory.list_checks|"hooks"->letd=List.map(fun(h:(moduleCore.Hook.HOOK))->letmoduleH=(valh)inH.name)(Core.Hook.list_hooks())inList.sort_uniqcompared|>Output.Factory.list_hooks|_->assertfalseinexit0));default="";}(** Output format *)let()=register_builtin_option{key="-format";category="Output";doc=" selects the output format.";spec=Symbol(["text";"json"],(funs->matchswith|"text"->Output.Common.(opt_format:=F_text)|"json"->Output.Common.(opt_format:=F_json);Debug.print_color:=false|_->assertfalse));default="text";}(** Output last flow *)let()=register_builtin_option{key="-lflow";category="Output";doc=" display the last output";spec=SetOutput.Common.opt_display_lastflow;default="false";}(** Ignore alarms when returning a value to the shell *)let()=register_builtin_option{key="-silent";category="Output";doc=" do not return a non-zero value when detecting alarms";spec=SetOutput.Common.opt_silent;default="unset";}(** Output stream *)let()=register_builtin_option{key="-output";category="Output";doc=" redirect output to a file";spec=String((funs->Output.Common.opt_file:=Somes),empty);default="";}let()=register_builtin_option{key="-show-callstacks";category="Alarms";doc=" display the call stacks when reporting alarms in text format";spec=SetOutput.Text.opt_show_callstacks;default="false";}let()=register_builtin_option{key="-tw";category="Output";doc=" set the tab width";spec=Set_int(Output.Text.opt_tw,strings["2";"4";"8"]);default="4";}let()=register_builtin_option{key="-show-safe-checks";category="Alarms";doc=" show safe checks when reporting alarms in text format";spec=SetOutput.Common.opt_show_safe_checks;default="false";}(** Apply cleaners on T_cur only *)let()=register_builtin_option{key="-clean-cur-only";category="Configuration";doc=" flag to apply cleaners on the current environment only";spec=SetCore.Cases.opt_clean_cur_only;default="";}let()=register_builtin_option{key="-hash-heap-address";category="Heap";doc=" format heap addresses with their hash";spec=Bool(funb->Core.Ast.Addr.opt_hash_addr:=b);default="false";}let()=register_builtin_option{key="-working-dir";category="Configuration";doc=" set the working directory, used when resolving relative paths";spec=String((funs->ifSys.file_existssthenSys.chdirselseExceptions.panic"'%s' does not exist"s),empty);default="";}let()=register_builtin_option{key="-marker";category="Partitioning";doc=" enable a marker for trace partitioning";spec=String(Core.Marker.enable_marker,funargs->ArgExt.strings(Core.Marker.available_markers())args);default="";}(** Help message *)lethelp()=letoptions=if!Config.Parser.opt_config=""thenList.mapopt_to_arg!optionselse(* Get the language and domains of selected configuration *)letconfig=Paths.resolve_config_file!Config.Parser.opt_configinletlang=Config.Parser.(languageconfig)inletdomains=Config.Parser.(domainsconfig)in(* Get the options *)(get_builtin_options())@(get_language_optionslang)@(List.mapget_domain_optionsdomains|>List.flatten)inOutput.Factory.helpoptionslet()=register_builtin_option{key="-help";category="Help";doc=" display the list of options";spec=Unit(fun()->help();exit0);default="";};register_builtin_option{key="--help";category="Help";doc=" display the list of options";spec=Unit(fun()->help();exit0);default="";};register_builtin_option{key="-h";category="Help";doc=" display the list of options";spec=Unit(fun()->help();exit0);default="";}(** Version *)letprint_version()=Printf.printf"%s (%s)\n"Version.versionVersion.dev_versionlet()=register_builtin_option{key="-v";category="Configuration";doc=" Mopsa version";spec=Unit(fun()->print_version();exit0);default="";}