123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2018-2019 The MOPSA Project. *)(* *)(* This program is free software: 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, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program 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. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(** Pretty-printing for CFG. *)openMopsaopenUniversal.AstopenAst(*==========================================================================*)(** {2 Text printing} *)(*==========================================================================*)letcfg_printer={CFG.print_node=(funfmtn->Format.fprintffmt"%a:@;"pp_node_id(CFG.node_idn));CFG.print_edge=(funfmte->Format.fprintffmt" @[<v>%a@]@;"pp_stmt(CFG.edge_datae));CFG.print_src=(funfmtnporte->Format.fprintffmt" %a --[%a]-->@;"pp_node_id(CFG.node_idn)pp_tokenport);CFG.print_dst=(funfmteportn->Format.fprintffmt" --[%a]--> %a@;"pp_tokenportpp_node_id(CFG.node_idn));CFG.print_entry=(funfmtnport->Format.fprintffmt" entry --[%a]--> %a@;"pp_tokenportpp_node_id(CFG.node_idn));CFG.print_exit=(funfmtnport->Format.fprintffmt" %a --[%a]--> exit@;"pp_node_id(CFG.node_idn)pp_tokenport);}let()=register_stmt_pp(funnextfmts->matchs.skindwith|S_cfgg->Format.fprintffmt"@[<v>%a@]"(CFG.printcfg_printer)g.cfg_graph|S_teste->Format.fprintffmt"test %a"pp_expre|S_skip->Format.pp_print_stringfmt"skip"|_->nextfmts)let()=register_token{compare=(funnextt1t2->matcht1,t2with|T_cfg_nodel1,T_cfg_nodel2->compare_node_idl1l2|T_cfg_edge_post(e1,p1),T_cfg_edge_post(e2,p2)->Compare.paircompare_edge_idcompare_token(e1,p1)(e2,p2)|T_cfg_entryp1,T_cfg_entryp2->compare_tokenp1p2|T_true,T_true->0|T_false,T_false->0|_->nextt1t2);print=(funnextfmtt->matchtwith|T_cfg_nodel->pp_node_idfmtl|T_cfg_edge_post(e,p)->Format.fprintffmt"-%a->%a"pp_edge_idepp_tokenp|T_cfg_entryp->Format.fprintffmt"->%a"pp_tokenp|T_true->Format.pp_print_stringfmt"true"|T_false->Format.pp_print_stringfmt"false"|_->nextfmtt);}(*==========================================================================*)(** {2 DOT output} *)(*==========================================================================*)letpp_location=Location.pp_positionletdot_printer={CFG.dot_pp_node=(funfmtn->pp_locationfmt(node_loc(CFG.node_idn)));CFG.dot_pp_edge=(funfmte->pp_stmtfmt(CFG.edge_datae));CFG.dot_pp_port=(funfmtt->pp_tokenfmtt);CFG.dot_filter_node=(funx->true);CFG.dot_filter_edge=(funx->true);CFG.dot_filter_port=(funx->true);}(** Prints the graph in dot format in the specified filename. *)letoutput_dot(title:string)(filename:string)(cfg:cfg):unit=letf=open_outfilenameinletfmt=Format.formatter_of_out_channelfinCFG.print_dotdot_printertitlefmtcfg.cfg_graph;Format.pp_print_flushfmt();close_outf