123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367(*
Copyright 2012-2020 Codinuum Software Lab <https://codinuum.com>
Copyright 2020-2025 Chiba Institute of Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)(* Author: Masatomo Hashimoto <m.hashimoto@stair.center> *)(* fact extractor *)[%%prepare_logger]moduleXset=Diffast_misc.XsetmoduleXprint=Diffast_misc.XprintmoduleBinding=Diffast_misc.BindingmoduleSourcecode=Diffast_core.SourcecodemoduleFact_base=Diffast_core.Fact_basemoduleTriple=Diffast_core.TriplemoduleAstml=Diffast_core.AstmlmoduleLabel=Cpp_labelmoduleTree=Cpp_treemoduleA=AstmlmoduleB=Binding[%%capture_pathmoduleF(L:Label.T)=structmoduleFB=Fact_base.F(L)openFBletgetlab=getlabletp_in_translation_unit=mkcppres"inTranslationUnit"letp_in_decl=mkcppres"inDeclaration"letp_in_simple_decl=mkcppres"inSimpleDeclaration"letp_in_func=mkcppres"inFunctionDefinition"letp_in_stmt=mkcppres"inStatement"letp_in_decl_stmt=mkcppres"inDeclarationStatement"letp_in_comp_stmt=mkcppres"inCompoundStatement"letp_in_try_block=mkcppres"inTryBlock"letp_in_if=mkcppres"inIfStatement"letp_in_switch=mkcppres"inSwitchStatement"letp_in_while=mkcppres"inWhileStatement"letp_in_do=mkcppres"inDoStatement"letp_in_for=mkcppres"inForStatement"letp_in_ranged_for=mkcppres"inRangeBasedForStatemennt"letp_in_container_unit=mkcppres"inContainerUnit"letp_in_pp_if_section=mkcppres"inPpIfSection"letp_in_pp_group=mkcppres"inPpGroup"letp_in_pp_if_group=mkcppres"inPpIfGroup"letp_in_pp_elif_group=mkcppres"inPpElifGroup"letp_in_pp_else_group=mkcppres"inPpElseGroup"letp_in_return=mkcppres"inReturnStatement"letp_in_call=mkcppres"inCall"letp_in_parameters=mkcppres"inParameters"letp_in_arguments=mkcppres"inArguments"letp_lhs=mkcppres"lhs"letp_rhs=mkcppres"rhs"letp_cond_of=mkcppres"conditionOf"letp_then_part_of=mkcppres"thenPartOf"letp_else_part_of=mkcppres"elsePartOf"letp_name=mkcppres"name"letp_path=mkcppres"path"letp_regexp=mkcppres"regexp"letp_value=mkcppres"value"letp_type_spec=mkcppres"typeSpecifier"letp_member=mkcppres"member"letp_member_name=mkcppres"memberName"letp_type=mkcppres"type"letp_requires=mkcppres"requires"letp_provides=mkcppres"provides"letp_declared_by=mkcppres"declaredBy"letp_refers_to=mkcppres"refersTo"letp_successor=mkcppres"successor"letnode_filteroptionsnd=(* filter out inactive nodes *)ifoptions#fact_restricted_flagthenletlab=getlabndinL.is_decllab||L.is_funclab||falseelsetrueletnode_pair_filteroptionsnd1nd2=(node_filteroptionsnd1)&&(node_filteroptionsnd2)letget_paramsnd=letparams=ref[]inbegintryArray.iter(funcnd->ifL.is_dtor(getlabcnd)thenletpnd=find_nodeL.is_param_decl_clausecndinparams:=Array.to_listpnd#initial_children)nd#initial_childrenwithNot_found->()end;!paramsletis_staticnd=tryignore(find_nodeL.is_staticnd);truewithNot_found->falseletis_externnd=tryignore(find_nodeL.is_externnd);truewithNot_found->falseletname_sep_pat=Str.regexp_string";"letconv_pat=letpat_conv_tbl=[Str.regexp_string"\\(","(";Str.regexp_string"\\)",")";Str.regexp_string"\\|","|";]infunx->List.fold_left(funs(re,rpl)->Str.global_replacererpls)xpat_conv_tblletmkpatn="^"^(conv_pat(String.lowercase_asciin))^"$"letis_patx=String.containsx'|'classextractoroptionscache_pathtree=object(self)inheritextractor_baseoptionscache_pathtreeassupermethod!id="Cpp"method!mkextnamen=super#mkextnamenmethod!scanner_body_after_subscanndlabentity=ifnode_filteroptionsndthenbeginself#add(entity,p_is_a,mkcppresnd#data#get_category);(* self#add (entity, p_file_digest, tree#encoded_source_digest); *)begintryArray.iteri(funic->letnth=nd#data#get_ordinaliinself#add(entity,p_childxnth,self#mkentityc))nd#initial_childrenwithNot_found->Array.iter(func->self#add(entity,p_child0,self#mkentityc))nd#initial_childrenend;beginXset.iter(funsucc->self#add(entity,p_successor,self#mkentitysucc))nd#data#successorsend;beginleta=(Obj.objnd#data#_annotation:Label.annotation)inLabel.Annotation.iter(function|Label.Annotation.Requirens->List.iter(funn->leten=self#mkextnameninself#add(en,p_is_a,Triple.c_external_name);self#add(en,p_name,mklitn);self#add(entity,p_requires,en))ns|Label.Annotation.Providens->List.iter(fun_n->List.iter(funn->leten=self#mkextnameninself#add(en,p_is_a,Triple.c_external_name);ifis_patnthenself#add(en,p_regexp,mklit(mkpatn))elseself#add(en,p_name,mklitn);self#add(entity,p_provides,en))(Str.splitname_sep_pat_n))ns|Label.Annotation.Types->self#add(entity,p_type,mklits))aend;ifL.is_translation_unitlabthenbeginletfent=letfid=nd#data#source_fidiniffid=""thenself#fileentityelseTriple.mkent(Triple.___make_file_entity(Triple.get_enc_stroptions())fid)inself#add(entity,p_in_file,fent);self#set_versionentityend;begintryletpath=L.get_pp_include_pathlabinself#add(entity,p_path,mklitpath)withNot_found->()end;ifL.is_named_origlabthenbegintryList.iter(funn->self#add(entity,p_name,mklitn))(Str.splitname_sep_pat(L.get_namelab))withNot_found->()end;begintryletty,v=ifL.is_int_literallabthenlit_ty_int,(L.get_valuelab)elseifL.is_real_literallabthenlit_ty_real,(L.get_valuelab)elselit_ty_string,(L.get_valuelab)inself#add(entity,p_value,mklit~ty:tyv)withNot_found->()end;(*let is_included =
try
nd#data#src_loc.Loc.filename <> tree#root#data#src_loc.Loc.filename
with
_ -> false
in
let loc_opt =
if is_included then
Some nd#data#src_loc
else
None
in*)[%debug_log"nd=%s"nd#to_string];beginletb=nd#data#bindinginmatchbwith|B.Def(bid,_,_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|B.Use(bid,(*loc_opt*)_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|_->()end;beginList.iter(funb->matchbwith|B.Def(bid,_,_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|B.Use(bid,(*loc_opt*)_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|_->())nd#data#bindingsend;(*if L.is_func lab then begin
let func_name = nd#data#get_name in
self#add (entity, p_provides, mklit func_name);
end;*)self#add_surrounding_xxxL.is_translation_unitndentityp_in_translation_unit;self#add_surrounding_xxxL.is_declndentityp_in_decl;self#add_surrounding_xxxL.is_funcndentityp_in_func;self#add_surrounding_xxxL.is_forndentityp_in_for;self#add_surrounding_xxxL.is_ranged_forndentityp_in_ranged_for;self#add_surrounding_xxxL.is_dondentityp_in_do;self#add_surrounding_xxxL.is_whilendentityp_in_while;self#add_surrounding_xxxL.is_switchndentityp_in_switch;self#add_surrounding_xxxL.is_ifndentityp_in_if;self#add_surrounding_xxxL.is_returnndentityp_in_return;self#add_surrounding_xxxL.is_decl_stmtndentityp_in_decl_stmt;self#add_surrounding_xxxL.is_comp_stmtndentityp_in_comp_stmt;self#add_surrounding_xxxL.is_stmtndentityp_in_stmt;self#add_surrounding_xxxL.is_try_blockndentityp_in_try_block;self#add_surrounding_xxxL.is_simple_declndentityp_in_simple_decl;self#add_surrounding_xxxL.is_container_unitndentityp_in_container_unit;self#add_surrounding_xxxL.is_pp_if_sectionndentityp_in_pp_if_section;self#add_surrounding_xxxL.is_pp_if_groupndentityp_in_pp_if_group;self#add_surrounding_xxxL.is_pp_elif_groupndentityp_in_pp_elif_group;self#add_surrounding_xxxL.is_pp_else_groupndentityp_in_pp_else_group;end;end(* of class Cpp.Fact.F.extractor *)letwarning_msg=Xprint.warning~head:"[Cpp]"(* main function *)letextractoptionscache_pathtree=tryletextractor=newextractoroptionscache_pathtreeinextractor#set_lang_prefixAstml.cpp_prefix;extractor#extractwith|Triple.File_existss->warning_msg"file exists: \"%s\""s|Triple.Lock_failed->warning_msg"fact buffer is already locked."end(* of functor Fortran.Fact.F *)]