123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-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/>. *)(* *)(****************************************************************************)(** Flow-insensitive context *)openMopsa_utils.Eqtype('a,_)ctx_key=..type'actx_list=|Empty|Cons:(('a,'v)ctx_key*'v*'actx_list)->'actx_listtype'actx={list:'actx_list;timestamp:int;}typectx_pool={ctx_pool_equal:'a'v'w.('a,'v)ctx_key->('a,'w)ctx_key->('v,'w)eqoption;ctx_pool_print:'a'v.(Print.printer->'a->unit)->Format.formatter->('a,'v)ctx_key->'v->unit;}letpool=ref{ctx_pool_equal=(fun__->None);ctx_pool_print=(funppfmtkeyv->raiseNot_found);}letcounter=ref0letnextlist=incrcounter;{list;timestamp=!counter}letempty_ctx={list=Empty;timestamp=0}letsingleton_ctx_listkv=Cons(k,v,Empty)letsingleton_ctxkv=next(singleton_ctx_listkv)letrecmem_ctx_list:typev.('a,v)ctx_key->'actx_list->bool=funk->function|Empty->false|Cons(k',_,tl)->match!pool.ctx_pool_equalkk'with|None->mem_ctx_listktl|SomeEq->trueletmem_ctxkctx=mem_ctx_listkctx.listletrecfind_ctx_list_opt:typev.('a,v)ctx_key->'actx_list->voption=funk->function|Empty->None|Cons(k',v,tl)->match!pool.ctx_pool_equalkk'with|None->find_ctx_list_optktl|SomeEq->Somevletfind_ctx_optkctx=find_ctx_list_optkctx.listletfind_ctxkctx=matchfind_ctx_optkctxwith|None->raiseNot_found|Somev->vletrecadd_ctx_list:typev.('a,v)ctx_key->v->'actx_list->'actx_list=funkv->function|Empty->singleton_ctx_listkv|Cons(k',v',tl)->match!pool.ctx_pool_equalkk'with|None->Cons(k',v',add_ctx_listkvtl)|SomeEq->Cons(k,v,tl)letadd_ctxkvctx=next(add_ctx_listkvctx.list)letrecremove_ctx_list:typev.('a,v)ctx_key->'actx_list->'actx_list=funk->function|Empty->Empty|Cons(k',v',tl)->match!pool.ctx_pool_equalkk'with|None->Cons(k',v',remove_ctx_listktl)|SomeEq->tlletremove_ctxkctx=next(remove_ctx_listkctx.list)letmost_recent_ctxctx1ctx2=ifctx1.timestamp>=ctx2.timestampthenctx1elsectx2letpp_ctxppfmtctx=letreciter=function|Empty->[]|Cons(k,v,tl)->(funfmt->!pool.ctx_pool_printppfmtkv)::itertlinletfl=iterctx.listinFormat.(fprintffmt"@[<v>%a@]"(pp_print_list~pp_sep:(funfmt()->fprintffmt"@,")(funfmtf->ffmt))fl)typectx_info={ctx_equal:'a'v'w.ctx_pool->('a,'v)ctx_key->('a,'w)ctx_key->('v,'w)eqoption;ctx_print:'a'v.ctx_pool->(Print.printer->'a->unit)->Format.formatter->('a,'v)ctx_key->'v->unit;}letregister_ctxinfo=letold_pool=!poolinpool:={ctx_pool_equal=(fun(typeavw)(k1:(a,v)ctx_key)(k2:(a,w)ctx_key)->info.ctx_equalold_poolk1k2);ctx_pool_print=(fun(typeav)ppfmt(k:(a,v)ctx_key)(v:v)->info.ctx_printold_poolppfmtkv)}moduleGenContextKey(Value:sigtype'atvalprint:(Print.printer->'a->unit)->Format.formatter->'at->unitend):sigvalkey:('a,'aValue.t)ctx_keyend=structtype('a,_)ctx_key+=MyKey:('a,'aValue.t)ctx_keyletkey=MyKeylet()=register_ctx{ctx_equal=(letf:typeavw.ctx_pool->(a,v)ctx_key->(a,w)ctx_key->(v,w)eqoption=funpoolk1k2->matchk1,k2with|MyKey,MyKey->SomeEq|_->pool.ctx_pool_equalk1k2inf);ctx_print=(letf:typeav.ctx_pool->(Print.printer->a->unit)->Format.formatter->(a,v)ctx_key->v->unit=funpoolppfmtkv->matchkwith|MyKey->Value.printppfmtv|_->pool.ctx_pool_printppfmtkvinf)}endopenMopsa_utils.CallstackmoduleCallstackKey=GenContextKey(structtype'at=callstackletprintppfmtcs=pp_callstackfmtcsend)letcallstack_ctx_key=CallstackKey.key