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

📄 xref_utils.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 2 页
字号:
    false.%%% The following functions implement some of the operators recognized%%% in xref_compiler.erl.closure(S) ->    relation_to_graph(S).components(G) ->    %% Returns a plain set of sets.    from_term(digraph_utils:cyclic_strong_components(G), [[atom]]).condensation(G) ->    G2 = digraph_utils:condensation(G),    %% A relation. The result can be only be used by a few set operations.    R = graph_to_relation(G2),    true = digraph:delete(G2),    R.path(G, [E]) ->    path(G, [E,E]);path(G, P=[E1 | _]) ->    path(P, G, [[E1]]).use(G, V) ->    neighbours(to_external(V), G, reaching_neighbours, type(V)).call(G, V) ->    neighbours(to_external(V), G, reachable_neighbours, type(V)).regexpr({regexpr, RExpr}, Var) ->    Xs = match_list(to_external(Var), RExpr),    xset(Xs, type(Var));regexpr({ModExpr, FunExpr, ArityExpr}, Var) ->    Type = type(Var),    V1 = case {ModExpr,Type} of	     {{atom, Mod},[{ModType, _}]} ->		 restriction(Var, xset([Mod], [ModType]));	     {{regexpr, MExpr},[{ModType, _}]} ->		 Mods = match_list(to_external(domain(Var)), MExpr),		 restriction(Var, xset(Mods, [ModType]));	     {variable,_} ->		 Var;             {_,_} -> % Var is the empty set                 Var	 end,    V2 = case FunExpr of	     {atom, FunName} ->		 V1L = to_external(V1),		 xset(match_one(V1L, FunName, 2), Type);	     {regexpr, FExpr} ->		 V1L = to_external(V1),		 xset(match_many(V1L, FExpr, 2), Type);	     variable ->		 V1	 end,    case ArityExpr of 	{integer, Arity} ->	    V2L = to_external(V2),	    xset(match_one(V2L, Arity, 3), Type);	{regexpr, Expr} ->	    V2L = to_external(V2),	    xset(match_many(V2L, Expr, 3), Type);	variable ->	    V2    end.%% -> digraph()relation_to_graph(S) ->    G = digraph:new(),    Fun = fun({From, To}) -> 		  digraph:add_vertex(G, From),		  digraph:add_vertex(G, To),		  digraph:add_edge(G, From, To)	  end,    foreach(Fun, to_external(S)),    G.%% -> {ok, FileName} | Error | fault()%% Finds a module's BEAM file.find_beam(Module) when is_atom(Module) ->    case code:which(Module) of	non_existing ->	    error({no_such_module, Module});	preloaded ->	    {_M, _Bin, File} = code:get_object_code(Module),	    {ok, File};        cover_compiled ->	    error({cover_compiled, Module});	File ->	    {ok, File}    end;find_beam(Culprit) ->    erlang:fault(badarg, [Culprit]).%% options(Options, ValidOptions) -> {OptionValues, InvalidOptions}%%%% Options = [Option] | Option%% ValidOptions = [atom() | {OptionName, ValidValues}]%% OptionValues = [bool() | {OptionName, [term()]}]%% OptionName = atom()%% InvalidOptions = [Option]%% Option = OptionName | {OptionName, term()}%% ValidValues = [] | [DefaultValue | [ValidValue]] | [DefaultValue, Tester]%% ValidValue = DefaultValue = term()%% Tester = fun([term()]) -> bool()%%%% A Boolean Option has a name (an atom). A Value Option has a name%% (an atom) and a value (a term).%%%% ValidOptions enumerates allowed options - a Boolean Option is%% enumerated with its name, and a Value Option is enumerated with a%% pair {Name, Values}, where Name is the option's name and Values is%% a list of allowed values for the Value Option, the first one being%% the default value (by convention). An empty list of allowed values%% means that all terms are allowed as value (and that there is no%% default value). Also if the only allowed value is the default%% value, all terms are allowed as value. A function argument (Tester)%% may be used for testing the supplied values (useful for a path...)%% An allowed option must not be enumerated more than once, but%% allowed values may be duplicated.%%%% OptionValues is a list of option values, where member i is the%% value of option i in ValidOptions. The value of a Boolean Option is%% 'true' if the option name is mentioned in Options, otherwise%% 'false'. The value of a Value Option is a list of the option values%% mentioned in Options for the Value Option. If the Value Option is%% not mentioned in Options, the list contains the default value (if%% there is no default value, the list is empty), and if it is%% mentioned more than once, the values are sorted in standard order.%%%% InvalidOptions is a list of those options present in Options that%% do not match any allowed option mentioned in ValidOptions.%%options(Options, Valid) ->    split_options(Options, [], [], [], Valid).subprocess(Fun, Opts) ->    Pid = spawn_opt(Fun, Opts),    receive 	{Pid, Reply} -> Reply    end.format_error({error, Module, Error}) ->    Module:format_error(Error);format_error({file_error, FileName, Reason}) ->    io_lib:format("~s: ~p~n", [FileName, file:format_error(Reason)]);format_error({unrecognized_file, FileName}) ->    io_lib:format("~p is neither a regular file nor a directory~n", 		  [FileName]);format_error({no_such_module, Module}) ->    io_lib:format("Cannot find module ~p using the code path~n", [Module]);format_error({interpreted, Module}) ->    io_lib:format("Cannot use BEAM code of interpreted module ~p~n", [Module]);format_error(E) ->    io_lib:format("~p~n", [E]).%%%%  Local functions%%to_list(X) when is_atom(X) -> atom_to_list(X);to_list(X) when is_list(X) -> X.select_application_directories([FileName|FileNames], Dir, Flag, L) ->    case is_directory(FileName) of	true ->	    File = filename:basename(FileName),	    {Name, Vsn} = filename_to_application(File),	    ApplDir = {Name, Vsn, subdir(FileName, Dir, Flag)},	    select_application_directories(FileNames, Dir, Flag, [ApplDir|L]);	false ->	    select_application_directories(FileNames, Dir, Flag, L);	Error ->	    Error    end;select_application_directories([], _Dir, _Flag, L) ->    {ok,reverse(L)}.subdir(Dir, _, false) ->    Dir;subdir(Dir, SubDir, true) ->    EDir = filename:join(Dir, SubDir),    case is_directory(EDir) of	true -> EDir;	_FalseOrError -> Dir    end.%% Avoid "App-01.01" - the zeroes will be lost.filename2appl(File) ->    Pos = string:rstr(File, "-"),    true = Pos > 1,    V = string:sub_string(File, Pos+1),    true = string:len(V) > 0,    VsnT = string:tokens(V, "."),    ApplName = string:sub_string(File, 1, Pos-1),    Vsn = [list_to_integer(Vsn) || Vsn <- VsnT],    {list_to_atom(ApplName),Vsn}.find_files_dir(Dir, Recurse, Collect, Watch, L) ->    case file:list_dir(Dir) of	{ok, Files} ->	    find_files(sort(Files), Dir, Recurse, Collect, Watch, L);	{error, Error} ->	    [B | {E,J,U}] = L,	    [B | {[file_error(Dir, Error)|E],J,U}]    end.find_files([F | Fs], Dir, Recurse, Collect, Watch, L) ->    File = filename:join(Dir, F),    L1 = case file_info(File) of	     {ok, {_, directory, readable, _}} when Recurse ->		 find_files_dir(File, Recurse, Collect, Watch, L);             {ok, {_, directory, _, _}} ->		 L;	     Info ->		 [B | EJU = {E,J,U}] = L,		 Ext = filename:extension(File),		 C = member(Ext, Collect),		 case C of		     true ->			 case Info of			     {ok, {_, file, readable, _}} ->				 [[{Dir,F} | B] | EJU];			     {ok, {_, file, unreadable, _}} ->				 [B | {E,J,[File|U]}];			     Error ->				 [B | {[Error|E],J,U}]			 end;		     false ->			 case member(Ext, Watch) of			     true -> [B | {E,[File|J],U}];			     false -> L			 end		 end	 end,    find_files(Fs, Dir, Recurse, Collect, Watch, L1);find_files([], _Dir, _Recurse, _Collect, _Watch, L) ->    L.graph_to_relation(G) ->    Fun = fun(E) -> {_E, V1, V2, _Label} = digraph:edge(G, E), {V1, V2} end,    from_term(map(Fun, digraph:edges(G)), [{[atom],[atom]}]).path([E1, E2 | P], G, L) ->    case digraph:get_short_path(G, E1, E2) of	false ->	    false;	[_V | Vs] ->	    path([E2 | P], G, [Vs | L])    end;path([_], _G, L) ->    append(reverse(L)).neighbours(Vs, G, Fun, VT) ->    neighbours(Vs, G, Fun, VT, []).neighbours([V | Vs], G, Fun, VT, L) ->    Ns = digraph_utils:Fun([V], G),    neighbours(Ns, G, Fun, VT, L, V, Vs);neighbours([], _G, _Fun, [VT], L) ->    xset(L, [{VT,VT}]).neighbours([N | Ns], G, Fun, VT, L, V, Vs) when Fun =:= reachable_neighbours ->    neighbours(Ns, G, Fun, VT, [{V, N} | L], V, Vs);neighbours([N | Ns], G, Fun, VT, L, V, Vs) ->    neighbours(Ns, G, Fun, VT, [{N, V} | L], V, Vs);neighbours([], G, Fun, VT, L, _V, Vs) ->    neighbours(Vs, G, Fun, VT, L).match_list(L, RExpr) ->    {ok, Expr} = regexp:parse(RExpr),    filter(fun(E) -> match(E, Expr) end, L).match_one(VarL, Con, Col) ->    select_each(VarL, fun(E) -> Con =:= element(Col, E) end).match_many(VarL, RExpr, Col) ->    {ok, Expr} = regexp:parse(RExpr),        select_each(VarL, fun(E) -> match(element(Col, E), Expr) end).match(I, Expr) when is_integer(I) ->    S = integer_to_list(I),    {match, 1, length(S)} =:= regexp:first_match(S, Expr);match(A, Expr) when is_atom(A) ->    S = atom_to_list(A),    {match, 1, length(S)} =:= regexp:first_match(S, Expr).select_each([{Mod,Funs} | L], Pred) ->    case filter(Pred, Funs) of        [] ->             select_each(L, Pred);        NFuns ->             [{Mod,NFuns} | select_each(L, Pred)]    end;select_each([], _Pred) ->    [].split_options([O | Os], A, P, I, V) when is_atom(O) ->    split_options(Os, [O | A], P, I, V);split_options([O={Name,_} | Os], A, P, I, V) when is_atom(Name) ->    split_options(Os, A, [O | P], I, V);split_options([O | Os], A, P, I, V) ->    split_options(Os, A, P, [O | I], V);split_options([], A, P, I, V) ->    Atoms = to_external(set(A)),    Pairs = to_external(relation_to_family(relation(P))),    option_values(V, Atoms, Pairs, I, []);split_options(O, A, P, I, V) ->    split_options([O], A, P, I, V).option_values([O | Os], A, P, I, Vs) when is_atom(O) ->    option_values(Os, delete(O, A), P, I, [member(O, A) | Vs]);    option_values([{Name, AllowedValues} | Os], A, P, I, Vs) ->    case keysearch(Name, 1, P) of	{value, {_, Values}} ->	    option_value(Name, AllowedValues, Values, A, P, I, Vs, Os);	false when AllowedValues =:= [] ->	    option_values(Os, A, P, I, [[] | Vs]);	false ->	    [Default | _] = AllowedValues,	    option_values(Os, A, P, I, [[Default] | Vs])    end;option_values([], A, P, Invalid, Values) ->    I2 = to_external(family_to_relation(family(P))),    {reverse(Values), Invalid ++ A ++ I2}.option_value(Name, [_Deflt, Fun], Vals, A, P, I, Vs, Os)                                                   when is_function(Fun) ->    P1 = keydelete(Name, 1, P),    case Fun(Vals) of	true ->	    option_values(Os, A, P1, I, [Vals | Vs]);	false ->	    option_values(Os, A, [{Name,Vals} | P1], I, [[] | Vs])    end;option_value(Name, AllowedValues, Values, A, P, I, Vs, Os) ->    P1 = keydelete(Name, 1, P),    VS = set(Values),    AVS = set(AllowedValues),    V1 = to_external(intersection(VS, AVS)),    {V, NP} = case to_external(difference(VS, AVS)) of		  _ when AllowedValues =:= [] -> {Values,P1};		  [] -> {V1,P1};		  _ when length(AllowedValues) =:= 1 -> 		      {Values,P1}; 		  I1 -> {V1,[{Name,I1} | P1]}	      end,    option_values(Os, A, NP, I, [V | Vs]).file_error(File, Error) ->    error({file_error, File, Error}).error(Error) ->    {error, ?MODULE, Error}.

⌨️ 快捷键说明

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