123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543(**************************************************************************)(* *)(* 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). *)(* *)(**************************************************************************)(* Data for a GUI-based pivot table *)openCil_typesmodulePivotSourceState=State_builder.List_ref(Datatype.List(Datatype.String))(structletname="PivotSourceState"letdependencies=[Ast.self;Eva.Analysis.self;Property_status.self;Messages.self]end)typesyntax_domain=|Code|Declaration|Annotationtypemessage_domain=Log.kindtypedomain=|Syntaxofsyntax_domain|Property|Messageofmessage_domainletstring_of_string_listsep=Format.asprintf"%a"(Pretty_utils.pp_list~pre:""~suf:""~sepFormat.pp_print_string)letsplit_loc(loc:Cil_types.location)=letfp=(fstloc).pos_pathinletline=string_of_int(fstloc).pos_lnuminletfp_pretty=Filepath.Normalized.to_pretty_stringfpinletdir=Filename.dirnamefp_prettyinletname=Filename.basenamefp_prettyinletext=Filename.extensionnameindir,name,ext,lineletnode_of_instr=function|Set_->"assignment"|Call_->"call"|Local_init_->"local_init"|Asm_->"asm"|Skip_->"nop"|Code_annot_->(* should be done by the annotations visitor *)assertfalseletopt_node_of_stmtkind=function|Instr_->None|Return(_,_)->Some"return"|Goto(_,_)->Some"goto"|Break_->Some"break"|Continue_->Some"continue"|If(_,_,_,_)->Some"if"|Switch(_,_,_,_)->Some"switch"|Loop(_,_,_,_,_)->Some"loop"|Block_->None|UnspecifiedSequence_->Some"unspecified_sequence"|Throw(_,_)->Some"throw"|TryCatch(_,_,_)->Some"try_catch"|TryFinally(_,_,_)->Some"try_finally"|TryExcept(_,_,_,_)->Some"try_except"letnode_of_code_annotation_node=function|AAssert_->"assert"|AStmtSpec_->"stmt_spec"|AInvariant_->"invariant"|AVariant_->"variant"|AAssigns_->"assigns"|AAllocation_->"allocation"|APragma_->"ca_pragma"|AExtended_->"extended"letnode_of_global_annotation=function|Dfun_or_pred_->"logic_fun_or_pred"|Dvolatile_->"logic_volatile"|Daxiomatic_->"axiomatic"|Dtype_->"logic_type"|Dlemma_->"logic_lemma"|Dinvariant_->"invariant"|Dtype_annot_->"type_annot"|Dmodel_annot_->"model_annot"|Dextended_->"ga_extended"letdomain_and_node_of_global=function|GType_->Declaration,"gtype"|GCompTag_->Declaration,"gcomptag"|GCompTagDecl_->Declaration,"gcomptagdecl"|GEnumTag_->Declaration,"genumtag"|GEnumTagDecl_->Declaration,"genumtagdecl"|GVarDecl_->Declaration,"global_var"|GFunDecl_->Declaration,"gfundecl"|GVar_->Declaration,"gvar"|GFun_->Declaration,"gfun"|GAsm_->Code,"gasm"|GPragma_->Code,"gpragma"|GText_->Code,"gtext"|GAnnot_->Code,"gannot"letnames_of_global=function|GType(_,_)->[]|GCompTag(_,_)->[]|GCompTagDecl(_,_)->[]|GEnumTag(_,_)->[]|GEnumTagDecl(_,_)->[]|GVarDecl(vi,_)->[vi.vname]|GFunDecl(_,vi,_)->[vi.vname]|GVar(vi,_,_)->[vi.vname]|GFun({svar},_)->[svar.vname]|GAsm(_,_)->[]|GPragma(_,_)->[]|GText_->[]|GAnnot(_,_)->[]letname_of_logic_infoli=li.l_var_info.lv_nameletname_of_global_annotation=function|Dvolatile(_,_,_,_,_)->None|Dfun_or_pred(li,_)|Dinvariant(li,_)|Dtype_annot(li,_)->Some(name_of_logic_infoli)|Daxiomatic(name,_,_,_)|Dtype({lt_name=name},_)|Dlemma(name,_,_,_,_,_)|Dmodel_annot({mi_name=name},_)|Dextended({ext_name=name},_,_)->Somenameletnode_of_predicate_kind=function|Assert->"assert"|Check->"check"|Admit->"admit"letnode_of_property=function|Property.IPPredicateidp->Format.asprintf"%a"Property.pretty_predicate_kindidp.ip_kind|IPCodeAnnotica->node_of_code_annotation_nodeica.ica_ca.annot_content|IPAxiomatic_->"axiomatic"|IPLemma_->"lemma"|IPBehavior_->"behavior"|IPComplete_->"complete"|IPDisjoint_->"disjoint"|IPAllocation_->"allocates"|IPAssigns_->"assigns"|IPFrom_->"from"|IPDecrease_->"loop variant"|IPExtended_->"extended"|IPReachable_->"reachable"|IPPropertyInstance_->"instance"|IPTypeInvariant_->"type_invariant"|IPGlobalInvariant_->"global_invariant"|IPOther_->"other"letnames_of_property=function|Property.IPPredicateidp->idp.ip_pred.ip_content.tp_statement.pred_name|IPCodeAnnot_->[]|IPAxiomatic_->[]|IPLemma_->[]|IPBehavior_->[]|IPComplete_->[]|IPDisjoint_->[]|IPAllocation_->[]|IPAssigns_->[]|IPFrom_->[]|IPDecrease_->[]|IPExtended_->[]|IPReachable_->[]|IPPropertyInstance_->[]|IPTypeInvariant_->[]|IPGlobalInvariant_->[]|IPOther_->[]letplugin_of_emittersel=matchelwith|[]|["Call Preconditions"]|["Frama-C kernel"]->"kernel"|["Eva"]->"eva"|_->"<unknown emitters ("^string_of_string_list","el^")>"letstring_of_syntax_domain=function|Code->"code"|Declaration->"decl"|Annotation->"annot"letstring_of_message_domain=function|Log.Result->"result"|Feedback->"feedback"|Debug->"debug"|Warning->"warning"|Error->"error"|Failure->"failure"letsplit_domain=function|Syntaxd->"syntax",string_of_syntax_domaind|Property->"property",""|Messaged->"message",string_of_message_domaindmoduleFunctionAtPos=structlettbl:(Filepath.Normalized.t,(Filepath.position*Filepath.position*string)Array.t)Hashtbl.t=Hashtbl.create16letbinary_searchapos:stringoption=letcmp=Cil_datatype.Position.compareinletrecauxlohi=iflo>hithenNoneelseletmid=(hi+lo)/2inlet(mstart,mend,mfunc)=a.(mid)inifcmpposmstart>=0thenifcmpposmend<=0thenSomemfuncelseaux(mid+1)hielseauxlo(mid-1)inaux0(Array.lengtha-1)letcompute()=lettmp=Hashtbl.create16inletfiles=List.fold_left(funacc((pos1,_,_)astriple)->letfp=pos1.Filepath.pos_pathinHashtbl.addtmpfptriple;Datatype.Filepath.Set.addfpacc)Datatype.Filepath.Set.empty(Cabs2cil.func_locs())inHashtbl.cleartbl;Datatype.Filepath.Set.iter(funfp->letl=List.sort(fun(start1,_,_)(start2,_,_)->Cil_datatype.Position.comparestart1start2)(Hashtbl.find_alltmpfp)inHashtbl.replacetblfp(Array.of_listl))filesletfindpos=letfp=pos.Filepath.pos_pathinOption.bind(Hashtbl.find_opttblfp)(funa->binary_searchapos)endtypeentry={loc:Cil_datatype.Location.t;func:stringoption;domain:domain;plugin:string;status:string;node:string;names:stringlist;text:string;}letheaders=["Directory";"Filename";"Extension";"Line Number";"Function";"Domain";"Kind";"Plugin";"Status";"Node";"Names";"Text"]letadd_entry_strentry=letdir,fname,ext,line=split_locentry.locinletfuncname=Option.fold~none:""~some:Stdlib.Fun.identry.funcinletdomain,kind=split_domainentry.domaininletnames=string_of_string_list":"entry.namesinletentry=[dir;fname;ext;line;funcname;domain;kind;entry.plugin;entry.status;entry.node;names;entry.text]inifPivotSourceState.get()=[]thenPivotSourceState.addheaders;PivotSourceState.addentryletnew_entry?func?(plugin="")?(status="")?(node="")?(names=[])?(text="")locdomain={loc;func;domain;plugin;status;node;names;text}letadd_entry?func?plugin?status?node?names?textlocdomain=letentry=new_entry?func?plugin?status?node?names?textlocdomaininadd_entry_strentryclassfull_visitor=object(self)inheritCil.nopCilVisitorvalmutablecur_func=Nonemethodadd?func?node?namesdomain=letloc=Cil.CurrentLoc.get()inletfunc=iffunc<>None&&func<>Some""thenfuncelsecur_funcinadd_entry?func?node?nameslocdomainmethodadd_code?func?namesnode=self#add?func~node?names(SyntaxCode)methodadd_decl?func?namesnode=self#add?func~node?names(SyntaxDeclaration)methodadd_annot?namesnode=self#add~node?names(SyntaxAnnotation)method!vvrbl(_v:varinfo)=Cil.DoChildrenmethod!vvdec(_v:varinfo)=Cil.DoChildrenmethod!vexpr(_e:exp)=Cil.DoChildrenmethod!vlval(_l:lval)=Cil.DoChildrenmethod!voffs(_o:offset)=Cil.DoChildrenmethod!vinitoffs(_o:offset)=Cil.DoChildrenmethod!vinst(i:instr)=letnode=node_of_instriinself#add_codenode;Cil.DoChildrenmethod!vstmt(s:stmt)=beginmatchopt_node_of_stmtkinds.skindwith|None->()|Somenode->self#add_codenodeend;Cil.DoChildrenmethod!vfunc(f:fundec)=cur_func<-Somef.svar.vname;Cil.DoChildrenPost(funfd->cur_func<-None;fd)method!vglob(g:global)=letdomain,node=domain_and_node_of_globalginletnames=names_of_globalginletfunc="<global>"inifdomain=Declarationthenself#add_decl~func~namesnodeelseself#add_code~func~namesnode;Cil.DoChildrenmethod!vblock_=Cil.DoChildrenmethod!vinit___=Cil.DoChildrenmethod!vlocal_init__=Cil.DoChildrenmethod!vtype_=Cil.DoChildrenmethod!vcompinfo_=Cil.DoChildrenmethod!venuminfo_=Cil.DoChildrenmethod!vfieldinfo_=Cil.DoChildrenmethod!venumitem_=Cil.DoChildrenmethod!vattr_=Cil.DoChildrenmethod!vattrparam_=Cil.DoChildrenmethod!vmodel_info_=Cil.DoChildrenmethod!vlogic_type_=Cil.DoChildrenmethod!videntified_term_=Cil.DoChildrenmethod!vterm_=Cil.DoChildrenmethod!vterm_node_=Cil.DoChildrenmethod!vterm_lval_=Cil.DoChildrenmethod!vterm_lhost_=Cil.DoChildrenmethod!vterm_offset_=Cil.DoChildrenmethod!vlogic_label_=Cil.DoChildrenmethod!vlogic_info_decl_=Cil.DoChildrenmethod!vlogic_info_use_=Cil.DoChildrenmethod!vlogic_type_info_decl_=Cil.DoChildrenmethod!vlogic_type_info_use_=Cil.DoChildrenmethod!vlogic_type_def_=Cil.DoChildrenmethod!vlogic_ctor_info_decl_=Cil.DoChildrenmethod!vlogic_ctor_info_use_=Cil.DoChildrenmethod!vlogic_var_use_=Cil.DoChildrenmethod!vlogic_var_decl_=Cil.DoChildrenmethod!vquantifiers_=Cil.DoChildrenmethod!videntified_predicate_=(* should be done by the annotations visitor *)assertfalsemethod!vpredicate_node_=Cil.DoChildrenmethod!vpredicate_=Cil.DoChildrenmethod!vbehavior_=Cil.DoChildrenmethod!vassigns_=Cil.DoChildrenmethod!vfrees_=Cil.DoChildrenmethod!vallocates_=Cil.DoChildrenmethod!vallocation_=Cil.DoChildrenmethod!vloop_pragma_=Cil.DoChildrenmethod!vslice_pragma_=Cil.DoChildrenmethod!vimpact_pragma_=Cil.DoChildrenmethod!vdeps_=Cil.DoChildrenmethod!vfrom_=Cil.DoChildrenmethod!vcode_annot_=(* should be done by the annotations visitor *)assertfalsemethod!vannotationga=letnode=node_of_global_annotationgainletnames=Option.to_list(name_of_global_annotationga)inself#add_annot~namesnode;Cil.DoChildrenendletca_visitor_cur_func:stringoptionref=refNoneletca_visitor_cur_emitter=ref"<unknown>"classcode_annot_visitor=object(self)inheritCil.nopCilVisitormethodadd_annot?(names=[])node=letloc=Cil.CurrentLoc.get()inletfunc=!ca_visitor_cur_funcinletplugin=!ca_visitor_cur_emitterinletdomain=SyntaxAnnotationinadd_entry?func~plugin~node~nameslocdomainmethod!videntified_predicate{ip_content={tp_kind}}=letnode=node_of_predicate_kindtp_kindinself#add_annotnode;Cil.DoChildrenmethod!vcode_annotca=letcontent=ca.annot_contentinself#add_annot(node_of_code_annotation_nodecontent);Cil.DoChildrenmethod!vannotationga=letnode=node_of_global_annotationgainletnames=Option.to_list(name_of_global_annotationga)inself#add_annot~namesnode;Cil.DoChildrenendletvisit_annots()=letvis=newcode_annot_visitorinAnnotations.iter_all_code_annot(funstmtemitterca->letkf=Kernel_function.find_englobing_kfstmtinca_visitor_cur_func:=Some(Kernel_function.get_namekf);ca_visitor_cur_emitter:=Emitter.get_nameemitter;ignore(Cil.visitCilCodeAnnotation(vis:>Cil.cilVisitor)ca))letvisit_properties()=Property_status.iter(funip->letloc=Property.locationipinletfunc=Option.mapKernel_function.get_name(Property.get_kfip)inletemitters=Property_status.fold_on_statuses(funemitter_statusacc->Emitter.Usable_emitter.get_nameemitter.emitter::acc)ip[]inletplugin=plugin_of_emittersemittersinletdomain=Propertyinletstatus=Format.asprintf"%a"Property_status.Feedback.pretty(Property_status.Feedback.getip)inletnode=node_of_propertyipinletnames=names_of_propertyipinadd_entry?func~node~status~plugin~nameslocdomain)letvisit_messages()=FunctionAtPos.compute();Messages.iter(funev->letplugin=ev.evt_plugininletloc_of_posp=(p,p)inletloc,func=matchev.evt_sourcewith|None->Cil_datatype.Location.unknown,"<global>"|Somepos->letfuncname=matchFunctionAtPos.findposwith|None->Metrics_parameters.warning"FUNCTION NOT FOUND FOR NON-GLOBAL MESSAGE POS: %a"Cil_datatype.Position.pretty_debugpos;"<unknown>"|Somename->nameinloc_of_pospos,funcnameinletdomain=Message(ev.evt_kind)inlettext=ev.evt_messageinadd_entry~func~plugin~textlocdomain)(* Useful mainly for debugging *)let_pp_as_csv(data:stringlistlist)=letpp_list=string_of_string_list","inList.iter(funls->Format.printf"%s@\n"(pp_listls))(List.revdata)(* Server / Ivette stuff *)openServerletpackage=Package.package~plugin:"pivot"~name:"general"~title:"Pivot Table Services"()moduleTableState=structtypet=stringlistlistletjtype=Data.declare~package~name:"tableStateType"~descr:(Markdown.plain"State of the pivot table source data.")Package.(Jarray(JarrayJstring))letto_jsonll=`List(List.rev_map(funl->`List(List.map(funs->`Strings)l))ll)endletpivot_signal=States.register_value~package~name:"pivotState"~descr:(Markdown.plain"State of the pivot table source data.")~output:(moduleTableState)~get:PivotSourceState.get~add_hook:PivotSourceState.add_hook_on_update()letcompute()=letast=Ast.get()inletvis=newfull_visitorinignore(Cil.visitCilFile(vis:>Cil.cilVisitor)ast);visit_annots();visit_properties();visit_messages();(*_pp_as_csv (PivotSourceState.get ());*)(* Signals that the pivot table has been updated. *)Server.Request.emitpivot_signallet_compute=Server.Request.register~package~kind:`EXEC~name:"compute"~descr:(Markdown.plain"Computes the pivot table.")~input:(moduleData.Junit)~output:(moduleData.Junit)compute