123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155(****************************************************************************)(* *)(* 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/>. *)(* *)(****************************************************************************)(** Debug - Conditional debugging with channel filtering. *)letchannels=ref[]letprint_warnings=reftrueletprint_color=reftrueletprint_all=reffalseletwhite=1letred=9letgreen=0x28letyellow=0xbeletblue=12letmagenta=5letfushia=177letorange=0xd0letteal=6letgray=8letpink=162letadd_channelch=ifch="all"thenprint_all:=trueelseletch'=ch^"$"|>Str.global_replace(Str.regexp_string".")"\\."|>Str.global_replace(Str.regexp_string"_")".*"inletre=Str.regexpch'inchannels:=re::!channels(* Parse a list of channels separated by ',' *)letparseopt=Str.split(Str.regexp",")opt|>List.iteradd_channelletset_channelsopt=let()=channels:=[]inparseoptletcan_printchannel=!print_all||!channels|>List.exists(funre->Str.string_matchrechannel0)(** Gives a random map of channel colors *)letrandom_colorchannel=(Hashtbl.hashchannelmod26)*9+2letcolorcodeppfmtx=if!print_colorthenFormat.fprintffmt"\027[1;38;5;%dm%a\027[0m"codeppxelseFormat.fprintffmt"%a"ppxletcolor_strcfmts=colorcFormat.pp_print_stringfmtsletboldppfmtx=if!print_colorthenFormat.fprintffmt"\027[1m%a\027[0m"ppxelseFormat.fprintffmt"%a"ppxletpp_channelfmtchannel=if!print_colorthenFormat.fprintffmt"\027[1;38;5;%dm%s\027[0m"(random_colorchannel)channelelseFormat.pp_print_stringfmtchannelletpp_channel_with_timefmtchannel=if!print_colorthenFormat.printf"\027[1;38;5;%dm[%s %.3f]\027[0m"(random_colorchannel)channel(Sys.time())elseFormat.printf"[%s %.3f]"channel(Sys.time())letdebug?(channel="debug")fmt=ifcan_printchannelthenFormat.kasprintf(funstr->Format.printf"%a @[%s@]@."pp_channel_with_timechannelstr)fmtelseFormat.ifprintfFormat.std_formatterfmtletinfofmt=ifcan_print"info"thenFormat.kasprintf(funstr->Format.printf"[%a] %s@."(color_strorange)"*"str)fmtelseFormat.ifprintfFormat.std_formatterfmtletplurial_listfmtl=ifList.lengthl<=1then()elseFormat.pp_print_stringfmt"s"letplurial_intfmtn=ifn<=1then()elseFormat.pp_print_stringfmt"s"letpanicfmt=Format.kasprintf(funstr->Format.printf"%a: %s@."(color_strred)"panic"str)fmtletpanic_atrangefmt=Format.kasprintf(funstr->Format.printf"%a: panic: %s@."(colorredLocation.pp_range)rangestr)fmtletwarnfmt=if!print_warningsthenFormat.kasprintf(funstr->Format.eprintf"%a: %s@."(color_strorange)"warning"str)fmtelseFormat.ifprintfFormat.err_formatterfmtletwarn_atrangefmt=if!print_warningsthenFormat.kasprintf(funstr->Format.eprintf"%a: warning: %s@."(colororangeLocation.pp_range)rangestr)fmtelseFormat.ifprintfFormat.err_formatterfmt(* simple detection of terminal coloring capabilities, using TERM variable;
able to detect whether we are runnig under emacs and force no-color
*)letterminal_has_colors()=trymatchSys.getenv"TERM"with|"dumb"|""->false|_->true(* by default *)withNot_found->falselet()=print_color:=terminal_has_colors()