12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* alternatives) *)(* *)(* 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, version 2.1. *)(* *)(* It 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. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)let()=Plugin.is_share_visible()let()=Plugin.is_session_visible()includePlugin.Register(structletname="WP"letshortname="wp"lethelp="Proof by Weakest Precondition Calculus"end)(* localize all warnings inside WP *)letwarning?wkey?current=matchcurrentwith|None->warning?wkey~current:true|Someb->warning?wkey~current:bletwkey_hyp=register_warn_category"hypothesis"lethypothesis?current?source?emitwith?echo?once?appendtext=warning~wkey:wkey_hyp?current?source?emitwith?echo?once?appendtextletresetdemon=ref[]leton_resetf=resetdemon:=f::!resetdemonletreset()=List.iter(funf->f())!resetdemonlethas_dkey(k:category)=is_debug_key_enabledk(* ------------------------------------------------------------------------ *)(* --- WP Generation --- *)(* ------------------------------------------------------------------------ *)letwp_generation=add_group"Goal Generator"let()=Parameter_customize.set_groupwp_generationlet()=Parameter_customize.do_not_save()moduleWP=Action(structletoption_name="-wp"lethelp="Generate proof obligations for all (selected) properties."end)let()=on_resetWP.clearlet()=Parameter_customize.set_groupwp_generationmoduleDump=Action(structletoption_name="-wp-dump"lethelp="Dump WP calculus graph."end)let()=on_resetDump.clearlet()=Parameter_customize.set_groupwp_generationlet()=Parameter_customize.do_not_save()moduleFunctions=Kernel_function_set(structletoption_name="-wp-fct"letarg_name="f,..."lethelp="Select properties of given functions (defaults to all functions)."end)let()=on_resetFunctions.clearlet()=Parameter_customize.set_groupwp_generationlet()=Parameter_customize.do_not_save()moduleSkipFunctions=Kernel_function_set(structletoption_name="-wp-skip-fct"letarg_name="f,..."lethelp="Skip the specified functions (defaults to none)."end)let()=on_resetSkipFunctions.clearlet()=Parameter_customize.set_groupwp_generationlet()=Parameter_customize.do_not_save()moduleBehaviors=String_list(structletoption_name="-wp-bhv"letarg_name="b,..."lethelp="Select only properties belonging to listed behaviors (the name \"default!\" can be used to select the default anonymous behavior) of the selected functions (defaults to all behaviors)."end)let()=on_resetBehaviors.clearlet()=Parameter_customize.set_groupwp_generationlet()=Parameter_customize.do_not_save()let()=Parameter_customize.no_category()moduleProperties=String_list(structletoption_name="-wp-prop"letarg_name="p,..."lethelp="Select properties based names and category.\n\
Use +name or +category to select properties and -name or -category \
to remove them from the selection. The '+' sign can be omitted.\n\
Categories are: @lemma, @requires, @assigns, @ensures, @exits, \
@assert, @invariant, @variant, @breaks, @continues, @returns, \
@complete_behaviors, @disjoint_behaviors, @terminates, \
@decreases and @check (which includes all check clauses)."end)let()=on_resetProperties.clearlet()=Parameter_customize.set_groupwp_generationmoduleStatusAll=False(structletoption_name="-wp-status-all"lethelp="Select properties with any status."end)let()=Parameter_customize.set_groupwp_generationmoduleStatusTrue=False(structletoption_name="-wp-status-valid"lethelp="Select properties with status 'Valid'."end)let()=Parameter_customize.set_groupwp_generationmoduleStatusFalse=False(structletoption_name="-wp-status-invalid"lethelp="Select properties with status 'Invalid'."end)let()=Parameter_customize.set_groupwp_generationmoduleStatusMaybe=True(structletoption_name="-wp-status-maybe"lethelp="Select properties with status 'Maybe'."end)(* ------------------------------------------------------------------------ *)(* --- Selected Functions --- *)(* ------------------------------------------------------------------------ *)moduleFct=Cil_datatype.Kf.Settypefunctions=|Fct_none|Fct_all|Fct_skipofFct.t|Fct_listofFct.tletiter_fctphi=function|Fct_none->()|Fct_all->Globals.Functions.iterphi|Fct_skipfs->Globals.Functions.iter(funkf->ifnot(Fct.memkffs)thenphikf)|Fct_listfs->Fct.iterphifsletget_kfs()=ifFunctions.is_empty()thenifSkipFunctions.is_empty()thenFct_allelseFct_skip(SkipFunctions.get())elseFct_list(Fct.diff(Functions.get())(SkipFunctions.get()))letget_fct()=ifWP.get()||not(Functions.is_empty())||not(Behaviors.is_empty())||not(Properties.is_empty())thenget_kfs()elseFct_noneletiter_kff=iter_fctf(get_fct())(* ------------------------------------------------------------------------ *)(* --- Memory Models --- *)(* ------------------------------------------------------------------------ *)letwp_model=add_group"Model Selection"let()=Parameter_customize.set_groupwp_modelmoduleModel=String_list(structletoption_name="-wp-model"letarg_name="model+..."lethelp="Memory model selection. Available selectors:\n\
* 'Hoare' logic variables only\n\
* 'Typed' typed pointers only\n\
* '+nocast' no pointer cast\n\
* '+cast' unsafe pointer casts\n\
* '+raw' no logic variable\n\
* '+ref' by-reference-style pointers detection\n\
* '+nat/+int' natural / machine-integers arithmetics\n\
* '+real/+float' real / IEEE floating point arithmetics\n\
* 'Eva' (experimental) based on the results from Eva plugin"end)let()=Parameter_customize.set_groupwp_modelmoduleByValue=String_set(structletoption_name="-wp-unalias-vars"letarg_name="var,..."lethelp="Consider variable names non-aliased."end)let()=Parameter_customize.set_groupwp_modelmoduleByRef=String_set(structletoption_name="-wp-ref-vars"letarg_name="var,..."lethelp="Consider variable names by reference."end)let()=Parameter_customize.set_groupwp_modelmoduleInHeap=String_set(structletoption_name="-wp-alias-vars"letarg_name="var,..."lethelp="Consider variable names aliased."end)let()=Parameter_customize.set_groupwp_modelmoduleAliasInit=False(structletoption_name="-wp-alias-init"lethelp="Use initializers for aliasing propagation."end)let()=Parameter_customize.set_groupwp_modelmoduleInCtxt=String_set(structletoption_name="-wp-context-vars"letarg_name="var,..."lethelp="Consider variable names in isolated context."end)let()=Parameter_customize.set_groupwp_modelmoduleExternArrays=False(structletoption_name="-wp-extern-arrays"lethelp="Put some default size for extern arrays."end)let()=Parameter_customize.set_groupwp_modelmoduleWeakIntModel=False(structletoption_name="-wp-weak-int-model"lethelp="Suppress integral type side conditions within lemmas\n\
(possibly unsound)"end)let()=Parameter_customize.set_groupwp_modelmoduleLiterals=False(structletoption_name="-wp-literals"lethelp="Export content of string literals."end)let()=Parameter_customize.set_groupwp_modelmoduleVolatile=True(structletoption_name="-wp-volatile"lethelp="Sound modeling of volatile access.\n\
Use -wp-no-volatile to ignore volatile attributes."end)(* -------------------------------------------------------------------------- *)(* --- Region Model --- *)(* -------------------------------------------------------------------------- *)letwp_region=add_group"Region Analysis"let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion=False(structletoption_name="-wp-region"lethelp="Perform Region Analysis (experimental)"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion_fixpoint=True(structletoption_name="-wp-region-fixpoint"lethelp="Compute region aliasing fixpoint"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion_cluster=True(structletoption_name="-wp-region-cluster"lethelp="Compute region clustering fixpoint"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion_inline=True(structletoption_name="-wp-region-inline"lethelp="Inline aliased sub-clusters"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion_rw=True(structletoption_name="-wp-region-rw"lethelp="Written region are considered read-write by default"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion_pack=True(structletoption_name="-wp-region-pack"lethelp="Pack clusters by default"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.do_not_save()moduleRegion_flat=False(structletoption_name="-wp-region-flat"lethelp="Flatten arrays by default"end)let()=Parameter_customize.set_groupwp_regionmoduleRegion_annot=False(structletoption_name="-region-annot"lethelp="Register '@region' ACSL Annotations (auto with -wp-region)"end)let()=Parameter_customize.set_groupwp_regionlet()=Parameter_customize.is_invisible()moduleRegion_output_dot=Filepath(structletoption_name="-wp-region-output-dot"letarg_name="output.dot"letfile_kind="DOT"letexistence=Fc_Filepath.Indifferentlethelp="Outputs the region graph in DOT format to the specified file."end)(* ------------------------------------------------------------------------ *)(* --- WP Strategy --- *)(* ------------------------------------------------------------------------ *)letwp_strategy=add_group"Computation Strategies"let()=Parameter_customize.set_groupwp_strategymoduleInit=True(structletoption_name="-wp-init-const"lethelp="Use initializers for global const variables."end)let()=Parameter_customize.set_groupwp_strategymoduleCalleePreCond=True(structletoption_name="-wp-callee-precond"lethelp="Use pre-conditions of callee."end)let()=Parameter_customize.set_groupwp_strategymoduleRTE=False(structletoption_name="-wp-rte"lethelp="Generate RTE guards before WP."end)let()=Parameter_customize.set_groupwp_strategymoduleSmokeTests=False(structletoption_name="-wp-smoke-tests"lethelp="Smoke-tests : look for inconsistent contracts (best effort)"end)let()=Parameter_customize.set_groupwp_strategymoduleSmokeDeadassumes=True(structletoption_name="-wp-smoke-dead-assumes"lethelp="When generating smoke tests, look for dead assumes"end)let()=Parameter_customize.set_groupwp_strategymoduleSmokeDeadcode=True(structletoption_name="-wp-smoke-dead-code"lethelp="When generating smoke tests, look for unreachable code"end)let()=Parameter_customize.set_groupwp_strategymoduleSmokeDeadcall=True(structletoption_name="-wp-smoke-dead-call"lethelp="When generating smoke tests, look for non-terminating calls"end)let()=Parameter_customize.set_groupwp_strategymoduleSmokeDeadlocalinit=False(structletoption_name="-wp-smoke-dead-local-init"lethelp="When generating smoke tests, look for dead local variables \
initialization"end)let()=Parameter_customize.set_groupwp_strategymoduleSmokeDeadloop=True(structletoption_name="-wp-smoke-dead-loop"lethelp="When generating smoke tests, look for inconsistent loop invariants"end)let()=Parameter_customize.set_groupwp_strategymoduleSplitBranch=False(structletoption_name="-wp-split"lethelp="Split if-then-else into sub-goals (see also -wp-max-split)"end)let()=Parameter_customize.set_groupwp_strategymoduleSplitSwitch=True(structletoption_name="-wp-split-switch"lethelp="Split switch-cases into sub-goals (see also -wp-max-split)."end)let()=Parameter_customize.set_groupwp_strategymoduleSplitConj=False(structletoption_name="-wp-split-conj"lethelp="Split conjunctive goals into sub-goals"end)let()=Parameter_customize.set_groupwp_strategymoduleSplitCNF=Int(structletoption_name="-wp-split-cnf"letdefault=0letarg_name="N"lethelp="Apply CNF transformation on goals at depth N (default 0, -1 unlimited)"end)let()=Parameter_customize.set_groupwp_strategymoduleSplitMax=Int(structletoption_name="-wp-max-split"letdefault=1000letarg_name="n"lethelp="Set maximum number of splitted sub-goals (default 1000)"end)let()=Parameter_customize.set_groupwp_strategymoduleUnfoldAssigns=Int(structletoption_name="-wp-unfold-assigns"letdefault=0letarg_name="n"lethelp="Unfold up to <n> levels of aggregates and arrays in assigns.\n\
Value -1 means unlimited depth (default 0)"end)let()=Parameter_customize.set_groupwp_strategylet()=Parameter_customize.is_invisible()moduleDynCall=True(structletoption_name="-wp-dynamic"lethelp="Handle dynamic calls with specific annotations."end)(* NOT use DynCall.add_set_hook: it won't work for the positive version of
the option, as the default is already true. *)let()=Cmdline.run_after_configuring_stage(fun()->ifDynCall.is_set()thenwarning~current:false"Option -wp-dynamic is obsolete and will be removed \
at some point in the future. @@calls annotations are now handled \
directly in the kernel")let()=Parameter_customize.set_groupwp_strategymodulePrecondWeakening=False(structletoption_name="-wp-precond-weakening"lethelp="Discard pre-conditions of side behaviours (sound but incomplete optimisation)."end)let()=Parameter_customize.set_groupwp_strategymoduleTerminatesVariantHyp=False(structletoption_name="-wp-variant-with-terminates"lethelp="Prove loop variant under the termination hypothesis."end)(* ------------------------------------------------------------------------ *)(* --- Qed Simplifications --- *)(* ------------------------------------------------------------------------ *)letwp_simplifier=add_group"Qed Simplifications"let()=Parameter_customize.set_groupwp_simplifiermoduleSimpl=True(structletoption_name="-wp-simpl"lethelp="Enable Qed Simplifications."end)let()=Parameter_customize.set_groupwp_simplifiermoduleLet=True(structletoption_name="-wp-let"lethelp="Use variable elimination."end)let()=Parameter_customize.set_groupwp_simplifiermoduleCore=True(structletoption_name="-wp-core"lethelp="Lift core facts through branches."end)let()=Parameter_customize.set_groupwp_simplifiermodulePrune=True(structletoption_name="-wp-pruning"lethelp="Prune trivial branches."end)let()=Parameter_customize.set_groupwp_simplifiermoduleFilterInit=True(structletoption_name="-wp-filter-init"lethelp="Use aggressive filtering of initialization hypotheses."end)let()=Parameter_customize.set_groupwp_simplifiermoduleClean=True(structletoption_name="-wp-clean"lethelp="Use a simple cleaning in case of -wp-no-let."end)let()=Parameter_customize.set_groupwp_simplifiermoduleGround=True(structletoption_name="-wp-ground"lethelp="Use aggressive ground simplifications."end)let()=Parameter_customize.set_groupwp_simplifiermoduleReduce=True(structletoption_name="-wp-reduce"lethelp="Reduce function equalities with precedence to constructors."end)let()=Parameter_customize.set_groupwp_simplifiermoduleExtEqual=True(structletoption_name="-wp-extensional"lethelp="Use extensional equality on compounds (hypotheses only)."end)let()=Parameter_customize.set_groupwp_simplifiermoduleFilter=True(structletoption_name="-wp-filter"lethelp="Filter non-used variables and related hypotheses."end)let()=Parameter_customize.set_groupwp_simplifiermoduleParasite=True(structletoption_name="-wp-parasite"lethelp="Use singleton-variable filtering."end)let()=Parameter_customize.set_groupwp_simplifiermodulePrenex=False(structletoption_name="-wp-prenex"lethelp="Normalize nested foralls into prenex-form"end)let()=Parameter_customize.set_groupwp_simplifiermoduleSimplifyIsCint=True(structletoption_name="-wp-simplify-is-cint"lethelp="Remove redundant machine integer range hypothesis."end)let()=Parameter_customize.set_groupwp_simplifiermoduleSimplifyLandMask=True(structletoption_name="-wp-simplify-land-mask"lethelp="Tight logical masks on unsigned integers."end)let()=Parameter_customize.set_groupwp_simplifiermoduleSimplifyForall=False(structletoption_name="-wp-simplify-forall"lethelp="Remove machine integer ranges in quantifiers."end)let()=Parameter_customize.set_groupwp_simplifiermoduleSimplifyType=False(structletoption_name="-wp-simplify-type"lethelp="Remove all `Type` constraints."end)let()=Parameter_customize.set_groupwp_simplifiermoduleInitWithForall=True(structletoption_name="-wp-init-summarize-array"lethelp="Summarize contiguous initializers with quantifiers."end)let()=Parameter_customize.set_groupwp_simplifiermoduleBoundForallUnfolding=Int(structletoption_name="-wp-bound-forall-unfolding"lethelp="Instantiate up to <n> forall-integers hypotheses."letarg_name="n"letdefault=1000end)(* ------------------------------------------------------------------------ *)(* --- Prover Interface --- *)(* ------------------------------------------------------------------------ *)letwp_prover=add_group"Prover Interface"let()=Parameter_customize.set_groupwp_provermoduleProvers=String_list(structletoption_name="-wp-prover"letarg_name="dp,..."lethelp="Submit proof obligations to prover(s):\n\
- 'none' (no prover run)\n\
- 'script' (replay all session scripts)\n\
- 'tip' (replay or init scripts for failed goals)\n\
- '<why3-prover>' (any Why-3 prover, see -wp-detect)\n\
"end)let()=Parameter_customize.set_groupwp_provermoduleInteractive=String(structletoption_name="-wp-interactive"letarg_name="mode"letdefault="batch"lethelp="WP mode for interactive Why-3 provers (eg: Coq):\n\
- 'batch': check current proof (default)\n\
- 'update': check updated proof\n\
- 'edit': edit current proof\n\
- 'fix': check current proof and edit if needed\n\
- 'fixup': update proof, check it and edit if needed\n\
"end)let()=Parameter_customize.set_groupwp_provermoduleScriptMode=String(structletoption_name="-wp-script"letarg_name="mode"letdefault=""lethelp="WP mode for managing scripts and proof strategies:\n\
- 'batch': proof scripts are reused but not updated (default for script prover)\n\
- 'update': proof scripts are reused and updated (default for tip prover)\n\
- 'init': proof scripts are generated from scratch and saved\n\
- 'dry': proof scripts are explored from scratch and not saved\n\
See also option -wp-cache-env."end)let()=Parameter_customize.set_groupwp_provermoduleStrategyEngine=True(structletoption_name="-wp-strategy-engine"lethelp="Activate @strategy and @proof annotations. (default: yes)"end)let()=Parameter_customize.set_groupwp_provermoduleDefaultStrategies=String_list(structletoption_name="-wp-strategy"letarg_name="s,..."lethelp="Use the specified strategies as default."end)let()=Parameter_customize.set_groupwp_provermoduleRunAllProvers=False(structletoption_name="-wp-run-all-provers"lethelp="Run all specified provers on each goal not proved by Qed. \
Do not stop when a prover succeeds. (default: no)"end)let()=Parameter_customize.set_groupwp_provermoduleCache=String(structletoption_name="-wp-cache"letarg_name="mode"letdefault=""lethelp="WP cache mode:\n\
- 'none': no cache, run provers (default)\n\
- 'update': use cache or run provers and update cache\n\
- 'cleanup': update mode with garbage collection\n\
- 'replay': update mode with no cache update\n\
- 'rebuild': always run provers and update cache\n\
- 'offline': use cache but never run provers\n\
See also option -wp-cache-env."end)let()=Parameter_customize.set_groupwp_provermoduleCacheDir=String(structletoption_name="-wp-cache-dir"letarg_name="dir"letdefault=""lethelp="Specify global cache directory (no cleanup mode).\n\
By default, cache entries are stored in the WP session directory.\n\
See also option -wp-cache-env."end)let()=Parameter_customize.set_groupwp_provermoduleCacheEnv=False(structletoption_name="-wp-cache-env"lethelp="Gives environment variables precedence over command line\n\
for cache management:\n\
- FRAMAC_WP_SCRIPT overrides -wp-script\n\
- FRAMAC_WP_CACHE overrides -wp-cache\n\
- FRAMAC_WP_CACHEDIR overrides -wp-cache-dir\n\
Disabled by default."end)let()=Parameter_customize.set_groupwp_provermoduleCachePrint=False(structletoption_name="-wp-cache-print"lethelp="Show cache directory"end)let()=Parameter_customize.set_groupwp_provermoduleGenerate=False(structletoption_name="-wp-gen"lethelp="Only generate prover files (default: no)."end)let()=on_resetGenerate.clearlet()=Parameter_customize.set_groupwp_provermoduleScriptOnStdout=False(structletoption_name="-wp-script-on-stdout"lethelp="When enabled (default: no), display scripts on stdout \
instead of writing them on disk."end)let()=Parameter_customize.set_groupwp_provermodulePrepareScripts=Action(structletoption_name="-wp-prepare-scripts"lethelp="Initialize a script tracking directory in the session \
directory."end)let()=Parameter_customize.set_groupwp_provermoduleFinalizeScripts=Action(structletoption_name="-wp-finalize-scripts"lethelp="Remove untracked scripts according to the tracking directory \
if it does exist (does not remove anything otherwise)."end)let()=Parameter_customize.set_groupwp_provermoduleDryFinalizeScripts=False(structletoption_name="-wp-dry-finalize-scripts"lethelp="Scripts that might be removed by -wp-finalize-scripts are \
kept, a message is printed instead for each file. The marks \
directory is kept."end)let()=Parameter_customize.set_groupwp_provermoduleDetect=Action(structletoption_name="-wp-detect"lethelp="List installed provers."end)let()=on_resetDetect.clearmoduleTactics=String_list(structletoption_name="-wp-tactic"letarg_name="id,..."lethelp="Describe tactic. Use '?' for listing tactic names."end)let()=on_resetTactics.clearlet()=Parameter_customize.set_groupwp_provermoduleDrivers=Filepath_list(structletoption_name="-wp-driver"letarg_name="file,..."letfile_kind="WP library"letexistence=Fc_Filepath.Must_existlethelp="Load drivers for linking to external libraries"end)let()=Parameter_customize.set_groupwp_provermoduleSteps=Int(structletoption_name="-wp-steps"letdefault=0letarg_name="n"lethelp="Set number of steps for provers."end)let()=Parameter_customize.set_groupwp_provermoduleTimeout=Int(structletoption_name="-wp-timeout"letdefault=2letarg_name="t"lethelp=Printf.sprintf"Set the timeout (in seconds) for provers (default: %d)."defaultend)let()=Parameter_customize.set_groupwp_provermoduleMemlimit=Int(structletoption_name="-wp-memlimit"letdefault=1000letarg_name="m"lethelp=Printf.sprintf"Set the memory limit (in Mb) for provers (default: %d)."defaultend)let()=Parameter_customize.set_groupwp_provermoduleFctTimeout=Kernel_function_map(structincludeDatatype.Inttypekey=Cil_types.kernel_functionletof_string~key:_~prev:_s=Option.map(funs->tryint_of_stringswithFailure_->raise(Cannot_build("'"^s^"' is not an integer")))sletto_string~key:_=Option.mapstring_of_intend)(structletoption_name="-wp-fct-timeout"letarg_name="f1:t1,...,fn:tn"lethelp="Customize the WP timeout (in secondes) for each specified \
function (t1 seconds for f1, t2 for f2, etc)."letdefault=Kernel_function.Map.emptyend)let()=Parameter_customize.set_groupwp_provermoduleSmokeTimeout=Int(structletoption_name="-wp-smoke-timeout"letdefault=2letarg_name="n"lethelp=Printf.sprintf"Set the timeout (in seconds) for provers (default: %d)."defaultend)let()=Parameter_customize.set_groupwp_provermoduleInteractiveTimeout=Int(structletoption_name="-wp-interactive-timeout"letdefault=30letarg_name="time"lethelp=Printf.sprintf"Set the timeout (in seconds) for checking scripts\n\
of interactive provers (default: %d)."defaultend)let()=Parameter_customize.set_groupwp_provermoduleTimeExtra=Int(structletoption_name="-wp-time-extra"letdefault=5letarg_name="n"lethelp=Printf.sprintf"Set extra-time (in seconds) for proof replay (default: %d)."defaultend)let()=Parameter_customize.set_groupwp_provermoduleTimeMargin=Int(structletoption_name="-wp-time-margin"letdefault=2letarg_name="n"lethelp=Printf.sprintf"Set margin-time (in seconds) for considering a proof automatic.\n\
When using the 'tip' prover, scripts are created or cancelled\n\
if the proof time is greater or lower than (timeout - margin).\n\
(default: %d)."defaultend)let()=Parameter_customize.set_groupwp_provermoduleProcs=Int(structletoption_name="-wp-par"letarg_name="p"letdefault=4lethelp=Printf.sprintf"Number of parallel proof process (default: %d)"defaultend)let()=Parameter_customize.set_groupwp_provermoduleProofTrace=False(structletoption_name="-wp-proof-trace"lethelp="Keeps output of provers for valid POs (default: no)"end)(* ------------------------------------------------------------------------ *)(* --- Prover Options --- *)(* ------------------------------------------------------------------------ *)letwp_prover_options=add_group"Prover Options"let()=Parameter_customize.set_groupwp_provermoduleAuto=String_list(structletoption_name="-wp-auto"letarg_name="s"lethelp="Activate auto-search with strategy <s>.\n\
Use '-wp-auto <?>' for available strategies."end)let()=Parameter_customize.set_groupwp_provermoduleAutoDepth=Int(structletoption_name="-wp-auto-depth"letarg_name="n"letdefault=5lethelp="Depth of auto-search (-wp-auto only, default 5).\n\
Limits the number of nested level in strategies."end)let()=Parameter_customize.set_groupwp_provermoduleAutoWidth=Int(structletoption_name="-wp-auto-width"letarg_name="n"letdefault=10lethelp="Width of auto-search (-wp-auto only, default 10).\n\
Limits the number of pending goals in strategies."end)let()=Parameter_customize.set_groupwp_provermoduleBackTrack=Int(structletoption_name="-wp-auto-backtrack"letarg_name="n"letdefault=0lethelp="Backtracking limit (-wp-auto only, de-activated by default).\n\
Limits backtracking when applying strategies."end)let()=Parameter_customize.set_groupwp_prover_optionslet()=Parameter_customize.no_category()moduleWhy3Flags=String_list(structletoption_name="-wp-why3-opt"letarg_name="option,..."lethelp="Additional options for Why3"end)let()=Parameter_customize.set_groupwp_prover_optionslet()=Parameter_customize.no_category()moduleWhy3ExtraConfig=String_list(structletoption_name="-wp-why3-extra-config"letarg_name="file,..."lethelp="Additional config files for Why3"end)(* ------------------------------------------------------------------------ *)(* --- PO Management --- *)(* ------------------------------------------------------------------------ *)letwp_po=add_group"Proof Obligations"let()=Parameter_customize.set_groupwp_pomoduleTruncPropIdFileName=Int(structletoption_name="-wp-filename-truncation"letdefault=60letarg_name="n"lethelp="Truncate basename of proof obligation files after <n> characters.\n\
Since numbers can be added as suffixes to make theses names unique,\n\
filename lengths can be highter to <n>. No truncation is performed\n\
when the value equals to zero (default: 60)."end)let()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()modulePrint=Action(structletoption_name="-wp-print"lethelp="Pretty-prints proof obligations on standard output."end)let()=on_resetPrint.clearlet()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleStatus=Action(structletoption_name="-wp-status"lethelp="Pretty-prints pending proof obligations on standard output."end)let()=on_resetPrint.clearlet()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleReport=String_list(structletoption_name="-wp-report"letarg_name="report,..."lethelp="Report specification file(s)"end)let()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleReportJson=Filepath(structletoption_name="-wp-report-json"letarg_name="file.json"letfile_kind="JSON report"letexistence=Fc_Filepath.Indifferentlethelp="Output proof results in JSON format."end)let()=on_resetReportJson.clearlet()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleOldReportJson=String(structletoption_name="-wp-deprecated-report-json"letarg_name="file.json"letdefault=""lethelp="Output report in json format into given file.\n\
If the file already exists, it is used for\n\
stabilizing range of steps in other reports."end)let()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleReportName=String(structletoption_name="-wp-report-basename"letarg_name="file"letdefault="wp-report"lethelp=Printf.sprintf"Basename of generated reports (default %S)"defaultend)let()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleMemoryContext=True(structletoption_name="-wp-warn-memory-model"lethelp="Warn Against Memory Model Hypotheses"end)let()=Parameter_customize.set_groupwp_polet()=Parameter_customize.do_not_save()moduleCheckMemoryContext=False(structletoption_name="-wp-check-memory-model"lethelp="Insert memory model hypotheses in function contracts and \
check them on call. (experimental)"end)let()=Parameter_customize.set_groupwp_pomoduleOutputDir=Filepath(structletexistence=Fc_Filepath.Indifferentletoption_name="-wp-out"letarg_name="dir"letfile_kind="directory"lethelp="Set working directory for generated files.\n\
Defaults to some temporary directory."end)(* -------------------------------------------------------------------------- *)(* --- Output Dir --- *)(* -------------------------------------------------------------------------- *)letdkey=register_category"output"lethas_out()=Fc_Filepath.Normalized.is_empty(OutputDir.get())letmake_output_dirdir=tryifExtlib.mkdir~parents:truedir0o770thendebug~dkey"Created output directory '%a'"Fc_Filepath.Normalized.prettydirwithUnix.Unix_error(err,_,_)->letmsg=Unix.error_messageerrinabort"System Error (%s)@\nCan not create output directory '%a'"msgFc_Filepath.Normalized.prettydir(*[LC] Do not projectify this reference : it is common to all projects *)letunique_tmp:Fc_Filepath.Normalized.toptionref=refNoneletmake_tmp_dir():Fc_Filepath.Normalized.t=match!unique_tmpwith|None->lettmp=tryExtlib.temp_dir_cleanup_at_exit"wp"withExtlib.Temp_file_errors->abort"Cannot create temporary file: %s"sinunique_tmp:=Sometmp;debug~dkey"Created temporary directory '%a'"Fc_Filepath.Normalized.prettytmp;tmp|Sometmp->tmpletmake_gui_dir()=trylethome=trySys.getenv"USERPROFILE"(*Win32*)withNot_found->trySys.getenv"HOME"(*Unix like*)withNot_found->"."inletdir=Fc_Filepath.Normalized.of_string(home^"/"^".frama-c-wp")inifFc_Filepath.existsdir&&Fc_Filepath.is_dirdirthenExtlib.safe_remove_dir(dir:>string);make_output_dirdir;dirwith_->make_tmp_dir()(** call the construction of the directory only once *)letbase_output=refNoneletbase_output()=match!base_outputwith|None->letoutput=letdir=OutputDir.get()inifFc_Filepath.Normalized.is_emptydirthenifFc_config.is_guithenmake_gui_dir()elsemake_tmp_dir()elsebeginmake_output_dirdir;direndinbase_output:=Someoutput;Fc_Filepath.(add_symbolic_dir"WPOUT"output);output|Someoutput->outputletget_output()=letbase=base_output()inletproject=Project.current()inletname=Project.get_unique_nameprojectinifname="default"thenbaseelseletdir=Datatype.Filepath.concatbasenameinmake_output_dirdir;dirletget_output_dird=letbase=get_output()inletpath=Datatype.Filepath.concatbasedinmake_output_dirpath;path(* -------------------------------------------------------------------------- *)(* --- Session dir --- *)(* -------------------------------------------------------------------------- *)letdefault=Fc_Filepath.(Normalized.concat(pwd())"/.frama-c")lethas_session()=Session.is_set()||(Fc_Filepath.existsdefault&&Fc_Filepath.is_dirdefault)letget_session~force()=ifforcethenSession.get_dir"."elseifSession.is_set()thenSession.get()elseSession.get_dir"."letget_session_dir~forced=letbase=get_session~force()inletpath=Datatype.Filepath.concatbasedinifforcethenmake_output_dirpath;path(* -------------------------------------------------------------------------- *)(* --- Print Generated --- *)(* -------------------------------------------------------------------------- *)letcat_print_generated=register_category"print-generated"lethas_print_generated()=has_dkeycat_print_generatedletprint_generated?headerfile=letheader=matchheaderwith|None->Fc_Filepath.Normalized.to_pretty_stringfile|Somehead->headindebug~dkey:cat_print_generated"%S@\n%t@."headerbeginfunfmt->ifnot(Fc_Filepath.existsfile)thenFormat.pp_print_stringfmt"<missing file>"elseCommand.read_linesfile(funs->Format.pp_print_stringfmts;Format.pp_print_newlinefmt())end(* -------------------------------------------------------------------------- *)(* --- Debugging --- *)(* -------------------------------------------------------------------------- *)letprotecte=ifdebug_atleast1thenfalseelsematchewith|Sys.Break|Db.Cancel|Log.AbortError_|Log.AbortFatal_->false|_->true(* -------------------------------------------------------------------------- *)