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

📄 xref_base.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 4 页
字号:
var_type('AM')   -> {module, vertex};var_type('LM')   -> {module, vertex};var_type('M')    -> {module, vertex};var_type('UM')   -> {module, vertex};var_type('R')    -> {release, vertex};var_type('E')    -> {function, edge};var_type('EE')   -> {function, edge};var_type('LC')   -> {function, edge};var_type('UC')   -> {function, edge};var_type('XC')   -> {function, edge};var_type('AE')   -> {application, edge};    var_type('ME')   -> {module, edge};    var_type('RE')   -> {release, edge};var_type(_)      -> {foo, bar}.make_families(ModDictList, N) ->    Fun1 = fun({_,XMod}) -> XMod#xref_mod.data end,    Ss = from_sets(map(Fun1, ModDictList)),    %% io:format("~n~p <= module data <= ~p~n",     %%           [pack:lsize(Ss), pack:usize(Ss)]),    make_fams(N, Ss, []).make_fams(1, _Ss, L) ->    L;make_fams(I, Ss, L) ->    Fun = {external, fun(R) -> {element(1, R), element(I, R)} end},    make_fams(I-1, Ss, [projection(Fun, Ss) | L]).make_M2A(ModDictList) ->    Fun = fun({M,XMod}) -> {M, XMod#xref_mod.app_name} end,    Mod0 = family(map(Fun, ModDictList)),    Mod = family_to_relation(Mod0),    Mod.make_A2R(ApplDict) ->    AppDict = dict:to_list(ApplDict),    Fun = fun({A,XApp}) -> {A, XApp#xref_app.rel_name} end,    Appl0 = family(map(Fun, AppDict)),     AllApps = domain(Appl0),    Appl = family_to_relation(Appl0),    {Appl, AllApps}.do_set_up_1(XC) ->    %% Call Graph cross reference...    XCp = union_of_family(XC),    XC_1 = user_family(XCp),    %% I - functions used externally from some module    %% XU  - functions used externally per module.    I = range(XCp),    {XU, XPredefined} = make_predefined(I, domain(XC)),    {XC_1, XU, XPredefined}.make_predefined(I, CallingModules) ->    XPredefined0 = predefined_funs(I),    XPredefined1 = converse(substitution(1, XPredefined0)),    %% predefined funs in undefined modules are still undefined...    XPredefined2 = restriction(XPredefined1, CallingModules),    XPredefined = relation_to_family(XPredefined2),    XU = partition_family(1, I),    {XU, XPredefined}.predefined_funs(Functions) ->    specification({external, predef_fun()}, Functions).predef_fun() ->    PredefinedFuns = xref_utils:predefined_functions(),    fun({_M,F,A}) -> member({F,A}, PredefinedFuns) end.make_defat(Undef, DefAt0) ->    % Complete DefAt with unknown functions:    Zero = from_term(0),    DAL = family_projection(fun(S) -> constant_function(S, Zero) end, Undef),    family_union(DefAt0, DAL).%% -> {Unknown U Lib, Unknown, Lib} | throw(Error)make_libs(XU, F, AM, LibPath, LibDict) ->    Undef = family_difference(XU, F),    UM = difference(domain(family_to_relation(Undef)), AM),    Fs = case is_empty_set(UM) of	     true ->		 [];	     false when LibPath =:= code_path ->		 BFun = fun(M, A) -> case xref_utils:find_beam(M) of					 {ok, File} -> [File | A];					 _ -> A				     end			end,		 foldl(BFun, [], to_external(UM));	     false ->		 Libraries = dict:to_list(LibDict),		 Lb = restriction(a_function(Libraries), UM),		 MFun = fun({M,XLib}) -> 				#xref_lib{dir = Dir} = XLib,				xref_utils:module_filename(Dir, M)			end,		 map(MFun, to_external(Lb))	     end,    Fun = fun(FileName, Deprs) -> 		  case beam_lib:chunks(FileName, [exports, attributes]) of		      {ok, {M, [{exports,X}, {attributes,A}]}} ->			  Exports = mfa_exports(X, A, M),                          %% No warnings for bad attributes...                          {Deprecated,_Bad} = deprecated(A, Exports, M),                          {{M,Exports}, [{M,Deprecated} | Deprs]};		      Error ->			  throw(Error)		  end	  end,    {XL, DL} = mapfoldl(Fun, [], Fs),    LF = from_term(XL),    %% Undef is the first argument to make sure that the whole of LF    %% becomes garbage:    Lib = family_intersection(Undef, LF),    {B,_} = make_builtins(Undef),    DLib = family_union(Lib, B),    [DF_1,DF_21,DF_31,DF1] = depr_lib(4, DL, DL, [], [], DLib),    DF_2 = family_union(DF_21, DF_1),    DF_3 = family_union(DF_31, DF_2),    DF = family_union(DF1, DF_3),    U = family_difference(Undef, Lib),    {Undef, U, Lib, DF, DF_1, DF_2, DF_3}.depr_lib(0, _, _, LL, [], _Lib) ->    LL;depr_lib(I, [], DL, LL, L, Lib) ->    DT = family_intersection(Lib, from_term(L)),    depr_lib(I-1, DL, DL, [DT | LL], [], Lib);depr_lib(I, [{M,D} | Ds], DL, LL, L, Lib) ->    depr_lib(I, Ds, DL, LL, [{M,element(I, D)} | L], Lib).make_builtins(U0) ->    Tmp = family_to_relation(U0),    Fun2 = {external, fun({_M,{M,F,A}}) -> xref_utils:is_builtin(M, F, A) end},    B = relation_to_family(specification(Fun2, Tmp)),    U = family_difference(U0, B),    {B, U}.% Returns a family that may not be defined for all modules.user_family(R) ->    partition_family({external, fun({_MFA1, {M2,_,_}}) -> M2 end}, R).do_variables(State) ->    Fun = fun({Name, #xref_var{vtype = user}}, {P,U}) -> 		  {P,[Name | U]};	     ({Name, #xref_var{vtype = predef}}, A={P,U}) -> 		  case atom_to_list(Name) of		      [H|_] when H>= $a, H=<$z -> A;		      _Else -> {[Name | P], U}		  end;	     ({{tmp, V}, _}, A) -> 		  io:format("Bug in ~p: temporary ~p~n", [?MODULE, V]), A;	     (_V, A) -> A	  end,    {U,P} = foldl(Fun, {[],[]}, dict:to_list(State#xref.variables)),    {sort(P), sort(U)}.%% Throws away the variables derived from raw data.take_down(S) when S#xref.variables =:= not_set_up ->    S;take_down(S) ->    S#xref{variables = not_set_up}.make_query(Format, Args) ->    flatten(io_lib:format(Format, Args)).set_defaults([O | Os], [[V] | Vs], State) ->    NewState = set_def(O, V, State),    set_defaults(Os, Vs, NewState);set_defaults([], [], State) ->    State.set_def(builtins, Value, State) ->    State#xref{builtins_default = Value};set_def(recurse, Value, State) ->    State#xref{recurse_default = Value};set_def(verbose, Value, State) ->    State#xref{verbose_default = Value};set_def(warnings, Value, State) ->    State#xref{warnings_default = Value}.option_values([Option | Options], State) ->    Default = current_default(State, Option),    [{Option, [Default,true,false]} | option_values(Options, State)];option_values([], _State) ->    [].current_default(State, builtins) ->    State#xref.builtins_default;current_default(State, recurse) ->    State#xref.recurse_default;current_default(State, verbose) ->    State#xref.verbose_default;current_default(State, warnings) ->    State#xref.warnings_default.%% sets are used here to avoid long execution timesdo_info(S, modules) ->    D = sort(dict:to_list(S#xref.modules)),    map(fun({_M,XMod}) -> mod_info(XMod) end, D);do_info(S, applications) ->    AppMods = to_external(relation_to_family(relation(app_mods(S)))),    Sum = sum_mods(S, AppMods),    map(fun(AppSum) -> app_info(AppSum, S) end, Sum);do_info(S, releases) ->    {RA, RRA} = rel_apps(S),    rel_apps_sums(RA, RRA, S);do_info(S, libraries) ->    D = sort(dict:to_list(S#xref.libraries)),    map(fun({_L,XLib}) -> lib_info(XLib) end, D);do_info(_S, I) ->    error({no_such_info, I}).		      do_info(S, Type, E) when is_atom(E) ->    do_info(S, Type, [E]);do_info(S, modules, Modules0) when is_list(Modules0) ->    Modules = to_external(set(Modules0)),    XMods = find_info(Modules, S#xref.modules, no_such_module),    map(fun(XMod) -> mod_info(XMod) end, XMods);do_info(S, applications, Applications) when is_list(Applications) ->    _XA = find_info(Applications, S#xref.applications, no_such_application),    AM = relation(app_mods(S)),    App = set(Applications),    AppMods_S = relation_to_family(restriction(AM, App)),    AppSums = sum_mods(S, to_external(AppMods_S)),    map(fun(AppSum) -> app_info(AppSum, S) end, AppSums);do_info(S, releases, Releases) when is_list(Releases) ->    _XR = find_info(Releases, S#xref.releases, no_such_release),    {AR, RRA} = rel_apps(S),    AR_S = restriction(2, relation(AR), set(Releases)),    rel_apps_sums(to_external(AR_S), RRA, S);do_info(S, libraries, Libraries0) when is_list(Libraries0) ->    Libraries = to_external(set(Libraries0)),    XLibs = find_info(Libraries, S#xref.libraries, no_such_library),    map(fun(XLib) -> lib_info(XLib) end, XLibs);do_info(_S, I, J) when is_list(J) ->    throw_error({no_such_info, I}).find_info([E | Es], Dict, Error) ->    case dict:find(E, Dict) of	error ->	    throw_error({Error, E});	{ok, X} ->	    [X | find_info(Es, Dict, Error)]    end;find_info([], _Dict, _Error) ->        [].%% -> {[{AppName, RelName}], [{RelName, XApp}]}rel_apps(S) ->    D = sort(dict:to_list(S#xref.applications)),    Fun = fun({_A, XApp}, Acc={AR, RRA}) ->		  case XApp#xref_app.rel_name of		      [] -> Acc;		      [R] ->			  AppName = XApp#xref_app.name,			  {[{AppName, R} | AR], [{R, XApp} | RRA]}		  end	  end,    foldl(Fun, {[], []}, D).%% -> [{{RelName, [XApp]}, Sums}]rel_apps_sums(AR, RRA0, S) ->    AppMods = app_mods(S), % [{AppName, XMod}]    RRA1 = relation_to_family(relation(RRA0)),    RRA = inverse(substitution(1, RRA1)),     %% RRA is [{RelName,{RelName,[XApp]}}]    RelMods = relative_product1(relation(AR), relation(AppMods)),    RelAppsMods = relative_product1(RRA, RelMods),    RelsAppsMods = to_external(relation_to_family(RelAppsMods)),    %% [{{RelName, [XApp]}, [XMod]}]    Sum = sum_mods(S, RelsAppsMods),    map(fun(RelAppsSums) -> rel_info(RelAppsSums, S) end, Sum).%% -> [{AppName, XMod}]app_mods(S) ->    D = sort(dict:to_list(S#xref.modules)),    Fun = fun({_M,XMod}, Acc) -> 		  case XMod#xref_mod.app_name of		      [] -> Acc;		      [AppName] -> [{AppName, XMod} | Acc]		  end	  end,    foldl(Fun, [], D).mod_info(XMod) ->    #xref_mod{name = M, app_name = AppName, builtins = BuiltIns, 	       dir = Dir, info = Info} = XMod,    App = sup_info(AppName),    {M, [{application, App}, {builtins, BuiltIns}, {directory, Dir} | Info]}.app_info({AppName, ModSums}, S) ->    XApp = dict:fetch(AppName, S#xref.applications),    #xref_app{rel_name = RelName, vsn = Vsn, dir = Dir} = XApp,    Release = sup_info(RelName),    {AppName, [{directory,Dir}, {release, Release}, {version,Vsn} | ModSums]}.    rel_info({{RelName, XApps}, ModSums}, S) ->    NoApps = length(XApps),    XRel = dict:fetch(RelName, S#xref.releases),    Dir = XRel#xref_rel.dir,    {RelName, [{directory, Dir}, {no_applications, NoApps} | ModSums]}.lib_info(XLib) ->    #xref_lib{name = LibName, dir = Dir} = XLib,    {LibName, [{directory,Dir}]}.sup_info([]) -> [];sup_info([Name]) ->    [Name].sum_mods(S, AppsMods) ->    sum_mods(S, AppsMods, []).sum_mods(S, [{N, XMods} | NX], L) ->    sum_mods(S, NX, [{N, no_sum(S, XMods)} | L]);sum_mods(_S, [], L) ->    reverse(L).no_sum(S, L) when S#xref.mode =:= functions ->    no_sum(L, 0, 0, 0, 0, 0, 0, 0, 0, length(L));no_sum(S, L) when S#xref.mode =:= modules ->    [{no_analyzed_modules, length(L)}].no_sum([XMod | D], C0, UC0, LC0, XC0, UFC0, L0, X0, EV0, NoM) ->    [{no_calls, {C,UC}},      {no_function_calls, {LC,XC,UFC}},     {no_functions, {L,X}},     {no_inter_function_calls, EV}] = XMod#xref_mod.info,    no_sum(D, C0+C, UC0+UC, LC0+LC, XC0+XC, UFC0+UFC, L0+L, X0+X, EV0+EV, NoM);no_sum([], C, UC, LC, XC, UFC, L, X, EV, NoM) ->    [{no_analyzed_modules, NoM},     {no_calls, {C,UC}},      {no_function_calls, {LC,XC,UFC}},     {no_functions, {L,X}},      {no_inter_function_calls, EV}].%% -> ok | throw(Error)is_filename(F) when is_atom(F) ->    ok;is_filename(F) ->    case xref_utils:is_string(F, 31) of	true ->	    ok;	false ->	    throw_error({invalid_filename, F})    end.module_file(XMod) ->    xref_utils:module_filename(XMod#xref_mod.dir, XMod#xref_mod.name).warnings(_Flag, _Message, []) -> true;warnings(Flag, Message, [F | Fs]) ->    message(Flag, Message, F),    warnings(Flag, Message, Fs).%% pack(term()) -> term()%%%% The identify function. The returned term does not use more heap%% than the given term. Tuples that are equal (=:=/2) are made %% "the same".%%%% The process dictionary is used because it seems to be faster than%% anything else right now...%%%pack(T) -> T;pack(T) ->        PD = erase(),    NT = pack1(T),    %% true = T =:= NT,    %% io:format("erasing ~p elements...~n", [length(erase())]),    erase(), % wasting heap (and time)...    map(fun({K,V}) -> put(K, V) end, PD),    NT.pack1(C) when not is_tuple(C), not is_list(C) ->    C;pack1([T | Ts]) ->    %% don't store conscells...    [pack1(T) | pack1(Ts)];%% Optimization.pack1(T={Mod,Fun,_}) when is_atom(Mod), is_atom(Fun) -> % MFA    case get(T) of	undefined -> put(T, T), T;	NT -> NT    end;pack1({C, L}) when is_list(L) -> % CallAt    {pack1(C), L};pack1({MFA, L}) when is_integer(L) -> % DefAt    {pack1(MFA), L};%% End optimization.pack1([]) ->    [];pack1(T) -> % when tuple(T)    case get(T) of	undefined ->	    NT = tpack(T, size(T), []),	    put(NT, NT),	    NT;	NT ->	    NT    end.tpack(_T, 0, L) ->    list_to_tuple(L);tpack(T, I, L) ->    tpack(T, I-1, [pack1(element(I, T)) | L]).message(true, What, Arg) ->    case What of	reading_beam ->	    io:format("~s... ", Arg);	skipped_beam ->	    io:format("skipped (no debug information)~n", Arg);	no_debug_info ->	    io:format("Skipping ~s (no debug information)~n", Arg);	unresolved_summary1 ->	    io:format("~p: 1 unresolved call~n", Arg);	unresolved_summary ->	    io:format("~p: ~p unresolved calls~n", Arg);	jam ->	    io:format("Skipping ~s (probably JAM file)~n", [Arg]);	unreadable ->	    io:format("Skipping ~s (unreadable)~n", [Arg]);	xref_attr ->	    io:format("~s: Skipping 'xref' attribute ~w~n", Arg);        depr_attr ->            io:format("~s: Skipping 'deprecated' attribute ~w~n", Arg);	lib_search ->	    io:format("Scanning library path for BEAM files... ", []);	lib_check ->	    io:format("Checking library files... ", []);	set_up ->	    io:format("Setting up...", Arg);	done ->	    io:format("done~n", Arg);	error ->	    io:format("error~n", Arg);	Else ->	    io:format("~p~n", [{Else,Arg}])    end;message(_, _, _) ->    true.throw_error(Reason) ->    throw(error(Reason)).error(Reason) ->    {error, ?MODULE, Reason}.

⌨️ 快捷键说明

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