123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230(**************************************************************************)(* *)(* 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). *)(* *)(**************************************************************************)openWpotypescript=|NoScript|ScriptofFilepath.Normalized.t|DeprecatedofFilepath.Normalized.ttypemode=|Batch|Update|Dry|Initletparse_mode~origin~fallback=function|"batch"->Batch|"update"->Update|"dry"->Dry|"init"->Init|""->raiseNot_found|m->Wp_parameters.warning~current:false"Unknown %s mode %S (use %s instead)"originmfallback;raiseNot_foundmoduleMODE=WpContext.StaticGenerator(Datatype.Unit)(structtypekey=unittypedata=modeletname="Wp.Script.mode"letcompile()=tryifnot(Wp_parameters.CacheEnv.get())thenraiseNot_found;letorigin="FRAMAC_WP_SCRIPT"inparse_mode~origin~fallback:"-wp-script"(Sys.getenvorigin)withNot_found->tryletmode=Wp_parameters.ScriptMode.get()inparse_mode~origin:"-wp-script"~fallback:"batch"modewithNot_found->letprovers=Wp_parameters.Provers.get()inifList.mem"tip"proversthenUpdateelseifList.mem"script"proversthenBatchelseDryend)letget_mode=MODE.getletset_modem=MODE.set()mletscratch_mode()=matchMODE.get()with|Batch|Update->false|Dry|Init->trueletsaving_mode()=matchMODE.get()with|Update|Init->true|Batch|Dry->falseletfiles:(Filepath.Normalized.t,script)Hashtbl.t=Hashtbl.create32letjsonfile(dir:Datatype.Filepath.t)name=Filepath.Normalized.concatdir(name^".json")letget_script_dir~force=Wp_parameters.get_session_dir~force"script"letfilename~forcewpo=letdscript=get_script_dir~forceinjsonfiledscriptwpo.po_sid(* no model in name *)letlegacieswpo=letmid=WpContext.MODEL.idwpo.po_modelinletdscript=Wp_parameters.get_session_dir~force:false"script"inletdmodel=Wp_parameters.get_session_dir~force:falsemidin[jsonfiledscriptwpo.po_gid;jsonfiledmodelwpo.po_gid;]letgetwpo=letf=filename~force:falsewpointryHashtbl.findfilesfwithNot_found->letscript=ifFilepath.existsfthenScriptfelsetryletf'=List.findFilepath.exists(legacieswpo)inWp_parameters.warning~current:false"Deprecated script for '%s'"wpo.po_sid;Deprecatedf'withNot_found->NoScriptinHashtbl.addfilesfscript;scriptletpp_filefmts=Filepath.Normalized.(prettyfmts)letpp_script_forfmtwpo=matchgetwpowith|Scriptf->Format.fprintffmt"script '%a'"pp_filef|Deprecatedf->Format.fprintffmt"(deprecated) script '%a'"pp_filef|_->Format.fprintffmt"script '%a'"pp_file@@filename~force:falsewpoletexistswpo=matchgetwpowithNoScript->false|Script_|Deprecated_->trueletloadwpo=matchgetwpowith|NoScript->`Null|Scriptf|Deprecatedf->ifFilepath.existsfthenJson.load_filefelse`Nullletremovewpo=matchgetwpowith|NoScript->()|Scriptf->beginExtlib.safe_remove(f:>string);Hashtbl.replacefilesfNoScript;end|Deprecatedf0->beginWp_parameters.feedback"Removed deprecated script for '%s'"wpo.po_sid;Extlib.safe_remove(f0:>string);letf=filename~force:falsewpoinHashtbl.replacefilesfNoScript;endletsave~stdoutwpojs=letempty=matchjswith|`Null|`List[]|`Assoc[]->true|_->falseinifstdoutthenWp_parameters.result"Proof script for %s:@.%a"wpo.po_gid(Json.save_formatter~pretty:true)jselseifemptythenremovewpoelsematchgetwpowith|Scriptf->Json.save_filefjs|NoScript->beginletf=filename~force:truewpoinJson.save_filefjs;Hashtbl.replacefilesf(Scriptf);end|Deprecatedf0->beginWp_parameters.feedback"Upgraded script for '%s'"wpo.po_sid;Extlib.safe_remove(f0:>string);letf=filename~force:truewpoinJson.save_filefjs;Hashtbl.replacefilesf(Scriptf);endletget_marks_dir~force=letscripts=Wp_parameters.get_session_dir~force"script"inletpath=Datatype.Filepath.concatscripts".marks"inifforcethenWp_parameters.make_output_dirpath;pathletremove_marks~dry=letmarks=get_marks_dir~force:falseinifFilepath.existsmarks&&Filepath.is_dirmarksthenifdrythenWp_parameters.feedback"[dry] remove marks"elseExtlib.safe_remove_dir(marks:>string)letreset_marks()=remove_marks~dry:false;ignore@@get_marks_dir~force:trueletmarkgoal=letmarks=get_marks_dir~force:falseinifFilepath.existsmarks&&Filepath.is_dirmarksthenletmark=Datatype.Filepath.concatmarks(goal.po_sid^".json")inifFilepath.existsmarkthen()elseclose_out@@open_out(mark:>string)moduleStringSet=Datatype.String.Setletremove_unmarked_files~dry=letdir=get_script_dir~force:falseinifFilepath.existsdir&&Filepath.is_dirdirthenletmarks=get_marks_dir~force:falseinifFilepath.existsmarks&&Filepath.is_dirmarksthenbeginletfiles=Array.fold_left(funsf->StringSet.addfs)StringSet.empty(Filepath.readdirdir)inletmarks=Array.fold_left(funsf->StringSet.addfs)StringSet.empty(Filepath.readdirmarks)inletorphans=StringSet.difffilesmarksinletorphans=StringSet.remove".marks"orphansinletremovefile=letpath=Filepath.Normalized.concatdirfileinifdrythenWp_parameters.feedback"[dry] rm %a"Filepath.Normalized.prettypathelseFilepath.removepathinStringSet.iterremoveorphans;remove_marks~dryend