⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cover.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 4 页
字号:
    {{op,Line,Op,MungedExprL,MungedExprR}, Vars3};munge_expr({op,Line,Op,Expr}, Vars) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    {{op,Line,Op,MungedExpr}, Vars2};munge_expr({'catch',Line,Expr}, Vars) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    {{'catch',Line,MungedExpr}, Vars2};munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},	   Vars) when Vars#vars.is_guard=:=false->    {MungedExprM, Vars2} = munge_expr(ExprM, Vars),    {MungedExprF, Vars3} = munge_expr(ExprF, Vars2),    {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),    {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},	   Vars) when Vars#vars.is_guard=:=true ->    %% Difference in abstract format after preprocessing: BIF calls in guards    %% are translated to {remote,...} (which is not allowed as source form)    %% NOT NECESSARY FOR Vsn=raw_abstract_v1    munge_expr({call,Line1,ExprF,Exprs}, Vars);munge_expr({call,Line,Expr,Exprs}, Vars) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),    {{call,Line,MungedExpr,MungedExprs}, Vars3};munge_expr({lc,Line,Expr,LC}, Vars) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    {MungedLC, Vars3} = munge_lc(LC, Vars2, []),    {{lc,Line,MungedExpr,MungedLC}, Vars3};munge_expr({block,Line,Body}, Vars) ->    {MungedBody, Vars2} = munge_body(Body, Vars, []),    {{block,Line,MungedBody}, Vars2};munge_expr({'if',Line,Clauses}, Vars) ->     {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),    {{'if',Line,MungedClauses}, Vars2};munge_expr({'case',Line,Expr,Clauses}, Vars) ->    {MungedExpr,Vars2} = munge_expr(Expr,Vars),    {MungedClauses,Vars3} = munge_clauses(Clauses, Vars2, []),    {{'case',Line,MungedExpr,MungedClauses}, Vars3};munge_expr({'receive',Line,Clauses}, Vars) ->     {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),    {{'receive',Line,MungedClauses}, Vars2};munge_expr({'receive',Line,Clauses,Expr,Body}, Vars) ->    {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),    {MungedExpr, Vars3} = munge_expr(Expr, Vars2),    {MungedBody, Vars4} = munge_body(Body, Vars3, []),    {{'receive',Line,MungedClauses,MungedExpr,MungedBody}, Vars4};munge_expr({'try',Line,Exprs,Clauses,CatchClauses,After}, Vars) ->    {MungedExprs, Vars1} = munge_exprs(Exprs, Vars, []),    {MungedClauses, Vars2} = munge_clauses(Clauses, Vars1, []),    {MungedCatchClauses, Vars3} = munge_clauses(CatchClauses, Vars2, []),    {MungedAfter, Vars4} = munge_body(After, Vars3, []),    {{'try',Line,MungedExprs,MungedClauses,MungedCatchClauses,MungedAfter},      Vars4};%% Difference in abstract format after preprocessing: Funs get an extra%% element Extra.%% NOT NECESSARY FOR Vsn=raw_abstract_v1munge_expr({'fun',Line,{function,Name,Arity},_Extra}, Vars) ->    {{'fun',Line,{function,Name,Arity}}, Vars};munge_expr({'fun',Line,{clauses,Clauses},_Extra}, Vars) ->    {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),    {{'fun',Line,{clauses,MungedClauses}}, Vars2};munge_expr({'fun',Line,{clauses,Clauses}}, Vars) ->    %% Only for Vsn=raw_abstract_v1    {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),    {{'fun',Line,{clauses,MungedClauses}}, Vars2};munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof    {Form, Vars}.munge_exprs([Expr|Exprs], Vars, MungedExprs) when Vars#vars.is_guard=:=true,						  is_list(Expr) ->    {MungedExpr, _Vars} = munge_exprs(Expr, Vars, []),    munge_exprs(Exprs, Vars, [MungedExpr|MungedExprs]);munge_exprs([Expr|Exprs], Vars, MungedExprs) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    munge_exprs(Exprs, Vars2, [MungedExpr|MungedExprs]);munge_exprs([], Vars, MungedExprs) ->    {reverse(MungedExprs), Vars}.munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]);munge_lc([Expr|LC], Vars, MungedLC) ->    {MungedExpr, Vars2} = munge_expr(Expr, Vars),    munge_lc(LC, Vars2, [MungedExpr|MungedLC]);munge_lc([], Vars, MungedLC) ->    {reverse(MungedLC), Vars}.%%%--Analysis------------------------------------------------------------%% Collect data for all modulescollect(Nodes) ->    %% local node    MS = ets:fun2ms(fun({M,C}) when is_atom(M) -> {M,C} end),    AllClauses = ets:select(?COVER_TABLE,MS),    move_modules(AllClauses),        %% remote nodes    remote_collect('_',Nodes,false).%% Collect data for one modulecollect(Module,Clauses,Nodes) ->    %% local node    move_modules([{Module,Clauses}]),        %% remote nodes    remote_collect(Module,Nodes,false).%% When analysing, the data from the local ?COVER_TABLE is moved to the%% ?COLLECTION_TABLE. Resetting data in ?COVER_TABLEmove_modules([{Module,Clauses}|AllClauses]) ->    ets:insert(?COLLECTION_TABLE,{Module,Clauses}),    move_clauses(Clauses),    move_modules(AllClauses);move_modules([]) ->    ok.    move_clauses([{M,F,A,C,_L}|Clauses]) ->    Pattern = {#bump{module=M, function=F, arity=A, clause=C}, '_'},    Bumps = ets:match_object(?COVER_TABLE,Pattern),    lists:foreach(fun({Key,Val}) ->			  ets:insert(?COVER_TABLE, {Key,0}),			  insert_in_collection_table(Key,Val)		  end,		  Bumps),    move_clauses(Clauses);move_clauses([]) ->    ok.			  %% Given a .beam file, find the .erl file. Look first in same directory as%% the .beam file, then in <beamdir>/../srcfind_source(File0) ->    case filename:rootname(File0,".beam") of	File0 ->	    File0;	File ->	    InSameDir = File++".erl",	    case filelib:is_file(InSameDir) of		true -> 		    InSameDir;		false ->		    Dir = filename:dirname(File),		    Mod = filename:basename(File),		    InDotDotSrc = filename:join([Dir,"..","src",Mod++".erl"]),		    case filelib:is_file(InDotDotSrc) of			true ->			    InDotDotSrc;			false ->			    {beam,File0}		    end	    end    end.%% do_analyse(Module, Analysis, Level, Clauses)-> {ok,Answer} | {error,Error}%%   Clauses = [{Module,Function,Arity,Clause,Lines}]do_analyse(Module, Analysis, line, _Clauses) ->    Pattern = {#bump{module=Module},'_'},    Bumps = ets:match_object(?COLLECTION_TABLE, Pattern),    Fun = case Analysis of	      coverage ->		  fun({#bump{line=L}, 0}) ->			  {{Module,L}, {0,1}};		     ({#bump{line=L}, _N}) ->			  {{Module,L}, {1,0}}		  end;	      calls ->		  fun({#bump{line=L}, N}) ->			  {{Module,L}, N}		  end	  end,    Answer = lists:keysort(1, lists:map(Fun, Bumps)),    {ok, Answer};do_analyse(_Module, Analysis, clause, Clauses) ->    Fun = case Analysis of	      coverage ->		  fun({M,F,A,C,Ls}) ->			  Pattern = {#bump{module=M,function=F,arity=A,					   clause=C},0},			  Bumps = ets:match_object(?COLLECTION_TABLE, Pattern),			  NotCov = length(Bumps),			  {{M,F,A,C}, {Ls-NotCov, NotCov}}		  end;	      calls ->		  fun({M,F,A,C,_Ls}) ->			  Pattern = {#bump{module=M,function=F,arity=A,					   clause=C},'_'},			  Bumps = ets:match_object(?COLLECTION_TABLE, Pattern),			  {_Bump, Calls} = hd(lists:keysort(1, Bumps)),			  {{M,F,A,C}, Calls}		  end	  end,    Answer = lists:map(Fun, Clauses),    {ok, Answer};do_analyse(Module, Analysis, function, Clauses) ->    {ok, ClauseResult} = do_analyse(Module, Analysis, clause, Clauses),    Result = merge_clauses(ClauseResult, merge_fun(Analysis)),    {ok, Result};do_analyse(Module, Analysis, module, Clauses) ->    {ok, FunctionResult} = do_analyse(Module, Analysis, function, Clauses),    Result = merge_functions(FunctionResult, merge_fun(Analysis)),    {ok, {Module,Result}}.merge_fun(coverage) ->    fun({Cov1,NotCov1}, {Cov2,NotCov2}) ->	    {Cov1+Cov2, NotCov1+NotCov2}    end;merge_fun(calls) ->    fun(Calls1, Calls2) ->	    Calls1+Calls2    end.merge_clauses(Clauses, MFun) -> merge_clauses(Clauses, MFun, []).merge_clauses([{{M,F,A,_C1},R1},{{M,F,A,C2},R2}|Clauses], MFun, Result) ->    merge_clauses([{{M,F,A,C2},MFun(R1,R2)}|Clauses], MFun, Result);merge_clauses([{{M,F,A,_C},R}|Clauses], MFun, Result) ->    merge_clauses(Clauses, MFun, [{{M,F,A},R}|Result]);merge_clauses([], _Fun, Result) ->    reverse(Result).merge_functions([{_MFA,R}|Functions], MFun) ->    merge_functions(Functions, MFun, R);merge_functions([],_MFun) ->         % There are no clauses.    {0,0}.                           % No function can be covered or notcov.merge_functions([{_MFA,R}|Functions], MFun, Result) ->    merge_functions(Functions, MFun, MFun(Result, R));merge_functions([], _MFun, Result) ->    Result.%% do_analyse_to_file(Module,OutFile,ErlFile) -> {ok,OutFile} | {error,Error}%%   Module = atom()%%   OutFile = ErlFile = string()do_analyse_to_file(Module, OutFile, ErlFile, HTML) ->    case file:open(ErlFile, read) of	{ok, InFd} ->	    case file:open(OutFile, write) of		{ok, OutFd} ->		    if HTML -> 			    io:format(OutFd,				      "<html>\n"				      "<head><title>~s</title></head>"				      "<body bgcolor=white text=black>\n"				      "<pre>\n",				      [OutFile]);		       true -> ok		    end,		    		    %% Write some initial information to the output file		    {{Y,Mo,D},{H,Mi,S}} = calendar:local_time(),		    io:format(OutFd, "File generated from ~s by COVER "			             "~p-~s-~s at ~s:~s:~s~n",			      [ErlFile,			       Y,			       string:right(integer_to_list(Mo), 2, $0),			       string:right(integer_to_list(D),  2, $0),			       string:right(integer_to_list(H),  2, $0),			       string:right(integer_to_list(Mi), 2, $0),			       string:right(integer_to_list(S),  2, $0)]),		    io:format(OutFd, "~n"			             "**************************************"			             "**************************************"			             "~n~n", []),		    print_lines(Module, InFd, OutFd, 1, HTML),		    		    if HTML -> io:format(OutFd,"</pre>\n</body>\n</html>\n",[]);		       true -> ok		    end,		    file:close(OutFd),		    file:close(InFd),		    {ok, OutFile};		{error, Reason} ->		    {error, {file, OutFile, Reason}}	    end;	{error, Reason} ->	    {error, {file, ErlFile, Reason}}    end.print_lines(Module, InFd, OutFd, L, HTML) ->    case io:get_line(InFd, '') of	eof ->	    ignore; 	"%"++_=Line ->				%Comment line - not executed. 	    io:put_chars(OutFd, [tab(),Line]),	    print_lines(Module, InFd, OutFd, L+1, HTML);	RawLine ->	    Line = escape_lt_and_gt(RawLine,HTML),	    Pattern = {#bump{module=Module,line=L},'$1'},	    case ets:match(?COLLECTION_TABLE, Pattern) of		[] ->		    io:put_chars(OutFd, [tab(),Line]);		Ns ->		    N = lists:foldl(fun([Ni], Nacc) -> Nacc+Ni end, 0, Ns),		    if			N=:=0, HTML=:=true ->			    LineNoNL = Line -- "\n",			    Str = "     0",			    %%Str = string:right("0", 6, 32),			    RedLine = ["<font color=red>",Str,fill1(),				       LineNoNL,"</font>\n"],			    io:put_chars(OutFd, RedLine);			N<1000000 ->			    Str = string:right(integer_to_list(N), 6, 32),			    io:put_chars(OutFd, [Str,fill1(),Line]);			N<10000000 ->			    Str = integer_to_list(N),			    io:put_chars(OutFd, [Str,fill2(),Line]);			true ->			    Str = integer_to_list(N),			    io:put_chars(OutFd, [Str,fill3(),Line])		    end	    end,	    print_lines(Module, InFd, OutFd, L+1, HTML)    end.tab() ->  "        |  ".fill1() ->      "..|  ".fill2() ->       ".|  ".fill3() ->        "|  ".%%%--Export--------------------------------------------------------------do_export_table(Compiled, Imported, Fd) ->    ModList = merge(Imported,Compiled),    write_module_data(ModList,Fd).merge([{Module,File,_ImportFiles}|Imported],ModuleList) ->    case lists:keymember(Module,1,ModuleList) of	true ->	    merge(Imported,ModuleList);	false ->	    merge(Imported,[{Module,File}|ModuleList])    end;merge([],ModuleList) ->    ModuleList.write_module_data([{Module,File}|ModList],Fd) ->    write({file,Module,File},Fd),    [Clauses] = ets:lookup(?COLLECTION_TABLE,Module),    write(Clauses,Fd),    ModuleData = ets:match_object(?COLLECTION_TABLE,{#bump{module=Module},'_'}),    do_write_module_data(ModuleData,Fd),    write_module_data(ModList,Fd);write_module_data([],_Fd) ->    ok.do_write_module_data([H|T],Fd) ->    write(H,Fd),    do_write_module_data(T,Fd);do_write_module_data([],_Fd) ->    ok.write(Element,Fd) ->    Bin = term_to_binary(Element,[compressed]),    case size(Bin) of	Size when Size > 255 ->	    SizeBin = term_to_binary({'$size',Size}),	    file:write(Fd,<<(size(SizeBin)):8,SizeBin/binary,Bin/binary>>);	Size ->	    file:write(Fd,<<Size:8,Bin/binary>>)    end,    ok.    %%%--Import--------------------------------------------------------------do_import_to_table(Fd,ImportFile,Imported) ->    do_import_to_table(Fd,ImportFile,Imported,[]).do_import_to_table(Fd,ImportFile,Imported,DontImport) ->    case get_term(Fd) of	{file,Module,File} ->	    case add_imported(Module, File, ImportFile, Imported) of		{ok,NewImported} ->		    do_import_to_table(Fd,ImportFile,NewImported,DontImport);		dont_import ->		    do_import_to_table(Fd,ImportFile,Imported,				       [Module|DontImport])	    end;	{Key=#bump{module=Module},Val} ->	    case lists:member(Module,DontImport) of		false ->		    insert_in_collection_table(Key,Val);		true ->		    ok	    end,	    do_import_to_table(Fd,ImportFile,Imported,DontImport);	{Module,Clauses} ->	    case lists:member(Module,DontImport) of		false ->		    ets:insert(?COLLECTION_TABLE,{Module,Clauses});		true ->			    ok	    end,	    do_import_to_table(Fd,ImportFile,Imported,DontImport);	eof ->	    Imported    end.	    get_term(Fd) ->    case file:read(Fd,1) of	{ok,<<Size1:8>>} ->	    {ok,Bin1} = file:read(Fd,Size1),	    case binary_to_term(Bin1) of		{'$size',Size2} -> 		    {ok,Bin2} = file:read(Fd,Size2),		    binary_to_term(Bin2);		Term ->		    Term	    end;	eof ->	    eof    end.%%%--Reset---------------------------------------------------------------%% Reset main node and all remote nodesdo_reset_main_node(Module,Nodes) ->    do_reset(Module),    do_reset_collection_table(Module),    remote_reset(Module,Nodes).do_reset_collection_table(Module) ->    ets:delete(?COLLECTION_TABLE,Module),    ets:match_delete(?COLLECTION_TABLE, {#bump{module=Module},'_'}).%% do_reset(Module) -> ok%% The reset is done on a per-clause basis to avoid building%% long lists in the case of very large modulesdo_reset(Module) ->    [{Module,Clauses}] = ets:lookup(?COVER_TABLE, Module),    do_reset2(Clauses).do_reset2([{M,F,A,C,_L}|Clauses]) ->    Pattern = {#bump{module=M, function=F, arity=A, clause=C}, '_'},    Bumps = ets:match_object(?COVER_TABLE, Pattern),    lists:foreach(fun({Bump,_N}) ->			  ets:insert(?COVER_TABLE, {Bump,0})		  end,		  Bumps),    do_reset2(Clauses);do_reset2([]) ->    ok.    do_clear(Module) ->    ets:match_delete(?COVER_TABLE, {Module,'_'}),    ets:match_delete(?COVER_TABLE, {#bump{module=Module},'_'}),    ets:match_delete(?COLLECTION_TABLE, {#bump{module=Module},'_'}).%%%--Div-----------------------------------------------------------------reverse(List) ->    reverse(List,[]).reverse([H|T],Acc) ->    reverse(T,[H|Acc]);reverse([],Acc) ->    Acc.escape_lt_and_gt(Rawline,HTML) when HTML =/= true ->    Rawline;escape_lt_and_gt(Rawline,_HTML) ->    escape_lt_and_gt1(Rawline,[]).escape_lt_and_gt1([$<|T],Acc) ->    escape_lt_and_gt1(T,[$;,$t,$l,$&|Acc]);escape_lt_and_gt1([$>|T],Acc) ->    escape_lt_and_gt1(T,[$;,$t,$g,$&|Acc]);escape_lt_and_gt1([],Acc) ->    lists:reverse(Acc);escape_lt_and_gt1([H|T],Acc) ->    escape_lt_and_gt1(T,[H|Acc]).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -