123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* 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). *)(* *)(**************************************************************************)openCil_typestypeacsl_stats={mutablef_requires:int;(** number of requires in function contracts *)mutables_requires:int;(** number of requires in statement contracts *)mutablef_ensures:int;mutables_ensures:int;mutablef_behaviors:int;mutables_behaviors:int;mutablef_assumes:int;mutables_assumes:int;mutablef_assigns:int;mutables_assigns:int;(** does not include loop assigns. *)mutablef_froms:int;mutables_froms:int;(** does not include loop dependencies. *)mutableinvariants:int;mutableloop_assigns:int;mutableloop_froms:int;mutablevariants:int;mutableasserts:int;}letempty_acsl_stat()={f_requires=0;s_requires=0;f_ensures=0;s_ensures=0;f_behaviors=0;s_behaviors=0;f_assumes=0;s_assumes=0;f_assigns=0;s_assigns=0;f_froms=0;s_froms=0;invariants=0;loop_assigns=0;loop_froms=0;variants=0;asserts=0;}letincr_f_requiresstat=stat.f_requires<-stat.f_requires+1letincr_s_requiresstat=stat.s_requires<-stat.s_requires+1letincr_f_ensuresstat=stat.f_ensures<-stat.f_ensures+1letincr_s_ensuresstat=stat.s_ensures<-stat.s_ensures+1letincr_f_behaviorsstat=stat.f_behaviors<-stat.f_behaviors+1letincr_s_behaviorsstat=stat.s_behaviors<-stat.s_behaviors+1letincr_f_assumesstat=stat.f_assumes<-stat.f_assumes+1letincr_s_assumesstat=stat.s_assumes<-stat.s_assumes+1letincr_f_assignsstat=stat.f_assigns<-stat.f_assigns+1letincr_s_assignsstat=stat.s_assigns<-stat.s_assigns+1letincr_f_fromsstat=stat.f_froms<-stat.f_froms+1letincr_s_fromsstat=stat.s_froms<-stat.s_froms+1letincr_invariantsstat=stat.invariants<-stat.invariants+1letincr_loop_assignsstat=stat.loop_assigns<-stat.loop_assigns+1letincr_loop_fromsstat=stat.loop_froms<-stat.loop_froms+1letincr_variantsstat=stat.variants<-stat.variants+1letincr_assertsstat=stat.asserts<-stat.asserts+1letpretty_acsl_statsfmtstat=Format.fprintffmt"@[<v 0>requires: %d total, %d in function contracts,\
%d in statement contracts@;\
ensures: %d total, %d in function contracts, %d in statement contracts@;\
behaviors: %d total, %d in function contracts, %d in statement contracts@;\
assumes: %d total, %d in function contracts, %d in statement contracts@;\
assigns: %d total, %d in function contracts, %d in statement contracts@;\
froms: %d total, %d in function contracts, %d in statement contracts@;\
invariants: %d@;loop assigns: %d@;loop froms: %d@;variants: %d@;\
asserts: %d@;@]"(stat.f_requires+stat.s_requires)stat.f_requiresstat.s_requires(stat.f_ensures+stat.s_ensures)stat.f_ensuresstat.s_ensures(stat.f_behaviors+stat.s_behaviors)stat.f_behaviorsstat.s_behaviors(stat.f_assumes+stat.s_assumes)stat.f_assumesstat.s_assumes(stat.f_assigns+stat.s_assigns)stat.f_assignsstat.s_assigns(stat.f_froms+stat.s_froms)stat.f_fromsstat.s_fromsstat.invariantsstat.loop_assignsstat.loop_fromsstat.variantsstat.assertsletpretty_acsl_stats_htmlfmtstat=Format.fprintffmt"@[<v 0>@{<h3>Contract elements@}@;@{<table>@;\
@{<tr>@{<td>@}\
@{<td>total@}@{<td>function contract@}@{<td>statement contract@}@}@;\
@{<tr>@;@{<td class=\"entry\">requires@}@;\
@{<td class=\"stat\">%d@}@;@{<td class=\"stat\">%d@}@;\
@{<td class=\"stat\">%d@}@}@;\
@{<tr>@;@{<td class=\"entry\">requires@}@;\
@{<td class=\"stat\">%d@}@;@{<td class=\"stat\">%d@}@;\
@{<td class=\"stat\">%d@}@}@;\
@{<tr>@;@{<td class=\"entry\">requires@}@;\
@{<td class=\"stat\">%d@}@;@{<td class=\"stat\">%d@}@;\
@{<td class=\"stat\">%d@}@}@;\
@{<tr>@;@{<td class=\"entry\">requires@}@;\
@{<td class=\"stat\">%d@}@;@{<td class=\"stat\">%d@}@;\
@{<td class=\"stat\">%d@}@}@;\
@{<tr>@;@{<td class=\"entry\">requires@}@;\
@{<td class=\"stat\">%d@}@;@{<td class=\"stat\">%d@}@;\
@{<td class=\"stat\">%d@}@}@;\
@{<tr>@;@{<td class=\"entry\">requires@}@;\
@{<td class=\"stat\">%d@}@;@{<td class=\"stat\">%d@}@;\
@{<td class=\"stat\">%d@}@}@}@;\
@{<h3>Simple code annotations@}@{<table>@;\
@{<tr>@{<td class=\"entry\">invariants@}@{<td class=\"stat\">%d@}@}@;\
@{<tr>@{<td class=\"entry\">loop assigns@}@{<td class=\"stat\">%d@}@}@;\
@{<tr>@{<td class=\"entry\">loop froms@}@{<td class=\"stat\">%d@}@}@;\
@{<tr>@{<td class=\"entry\">variants@}@{<td class=\"stat\">%d@}@}@;\
@{<tr>@{<td class=\"entry\">asserts@}@{<td class=\"stat\">%d@}@}@;\
@}@]"(stat.f_requires+stat.s_requires)stat.f_requiresstat.s_requires(stat.f_ensures+stat.s_ensures)stat.f_ensuresstat.s_ensures(stat.f_behaviors+stat.s_behaviors)stat.f_behaviorsstat.s_behaviors(stat.f_assumes+stat.s_assumes)stat.f_assumesstat.s_assumes(stat.f_assigns+stat.s_assigns)stat.f_assignsstat.s_assigns(stat.f_froms+stat.s_froms)stat.f_fromsstat.s_fromsstat.invariantsstat.loop_assignsstat.loop_fromsstat.variantsstat.assertsmoduleAcsl_stats=Datatype.Make(structtypet=acsl_statsletreprs=[empty_acsl_stat()]letname="Metrics_acsl.acsl_stats"includeDatatype.Serializable_undefinedletpretty=pretty_acsl_statsend)moduleGlobal_acsl_stats=State_builder.Ref(Acsl_stats)(structletname="Metrics_acsl.Global_acsl_stats"letdependencies=[Ast.self;Annotations.code_annot_state;Annotations.funspec_state;Annotations.global_state]letdefault=empty_acsl_statend)moduleFunctions_acsl_stats=State_builder.Hashtbl(Kernel_function.Hashtbl)(Acsl_stats)(structletname="Metrics_acsl.Functions_acsl_stats"letdependencies=[Ast.self;Annotations.code_annot_state;Annotations.funspec_state]letsize=17end)letget_kf_statskf=tryFunctions_acsl_stats.findkfwithNot_found->empty_acsl_stat()moduleComputed=State_builder.False_ref(structletname="Metrics_acsl.Computed"letdependencies=[Global_acsl_stats.self;Functions_acsl_stats.self]end)lettreat_behaviorlocal_statskib=letincr_behaviors=ifki=Kglobalthenincr_f_behaviorselseincr_s_behaviorsinletincr_requires=ifki=Kglobalthenincr_f_requireselseincr_s_requiresinletincr_ensures=ifki=Kglobalthenincr_f_ensureselseincr_s_ensuresinletincr_assumes=ifki=Kglobalthenincr_f_assumeselseincr_s_assumesinletincr_assigns=ifki=Kglobalthenincr_f_assignselseincr_s_assignsinletincr_froms=ifki=Kglobalthenincr_f_fromselseincr_s_fromsinletincr_allf_=flocal_stats;f(Global_acsl_stats.get())inincr_allincr_behaviors();List.iter(incr_allincr_requires)b.b_requires;List.iter(incr_allincr_ensures)b.b_post_cond;List.iter(incr_allincr_assumes)b.b_assumes;(matchb.b_assignswith|WritesAny->()|Writesl->incr_allincr_assigns();List.iter(function|(_,FromAny)->()|(_,From_)->incr_allincr_froms())l)(*TODO: allocation *)letadd_function_contract_statskf=letlocal_stats=get_kf_statskfinlettreat_behavior_b=treat_behaviorlocal_statsKglobalbinAnnotations.iter_behaviorstreat_behaviorkfletadd_code_annot_statsstmt_ca=letkf=Kernel_function.find_englobing_kfstmtinletlocal_stats=get_kf_statskfinletincr_allf=flocal_stats;f(Global_acsl_stats.get())inmatchca.annot_contentwith|AAssert_->incr_allincr_asserts|AStmtSpec(_,spec)->List.iter(treat_behaviorlocal_stats(Kstmtstmt))spec.spec_behavior|AInvariant_->incr_allincr_invariants|AVariant_->incr_allincr_variants|AAssigns(_,WritesAny)->()|AAssigns(_,Writesl)->incr_allincr_loop_assigns;List.iter(function(_,FromAny)->()|(_,From_)->incr_allincr_loop_froms)l|AAllocation_->()(* TODO *)|APragma_|AExtended_->()letcompute()=ifnot(Computed.get())thenbeginAst.compute();Annotations.iter_all_code_annotadd_code_annot_stats;Globals.Functions.iteradd_function_contract_stats;Computed.settrue;endletget_global_stats()=compute();Global_acsl_stats.get()letdump_html_globalfmt=pretty_acsl_stats_htmlfmt(get_global_stats())letdump_html_by_functionfmt=compute();Functions_acsl_stats.iter(funkfstats->Format.fprintffmt"@{<h2>Function %a@}@;%a"Kernel_function.prettykfpretty_acsl_stats_htmlstats)letdump_acsl_statsfmt=Metrics_base.mk_hdr1fmt"ACSL Statistics";Format.pp_print_newlinefmt();ifMetrics_parameters.ByFunction.get()thenbegincompute();Functions_acsl_stats.iter(funkfstats->letkf_name=Format.asprintf"%a"Kernel_function.prettykfinFormat.fprintffmt"@[<v 2>%a@;%a@]@;"(Metrics_base.mk_hdr2)kf_namepretty_acsl_statsstats)endelsepretty_acsl_statsfmt(get_global_stats())letdump_acsl_stats_htmlfmt=Format.pp_set_formatter_stag_functionsfmtMetrics_base.html_stag_functions;Format.fprintffmt"@[<v 0> <!DOCTYPE html>@ \
@{<html>@ \
@{<head>@ \
@{<title>%s@}@ \
<meta charset=\"utf-8\">@ \
@{<style type=\"text/css\">%s@}@ \
@}@ \
@{<body>\
@[<v 2>@ \
@{<h1>%s@}@;\
%t@]@}@}@]@?""ACSL Metrics"Css_html.css(ifMetrics_parameters.ByFunction.get()then"Detailed ACSL statistics"else"Global ACSL statistics")(ifMetrics_parameters.ByFunction.get()thendump_html_globalelsedump_html_by_function)letdump()=ifnot(Metrics_parameters.OutputFile.is_empty())thenbeginletout=Metrics_parameters.OutputFile.get()intryletchan=open_out(out:>string)inletfmt=Format.formatter_of_out_channelchanin(matchMetrics_base.get_file_typeoutwith|Metrics_base.Html->dump_acsl_stats_htmlfmt|Metrics_base.Text->dump_acsl_statsfmt|Metrics_base.Json->Metrics_parameters.not_yet_implemented"JSON format for ACSL metrics");close_outchanwithSys_errors->Metrics_parameters.abort"Cannot open file %a (%s)"Filepath.Normalized.prettyoutsendelseMetrics_parameters.result"%t"dump_acsl_stats