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

📄 igor.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
    %% the target is the same as one of the source modules). It is    %% however not "safe" by default. If no modules are explicitly    %% specified as static, it is assumed that *all* are static.    Static0 = ordsets:from_list(proplists:append_values(static, Opts)),    case proplists:is_defined(static, Opts) of	false ->	    Static = All;	true ->	    Static = ordsets:add_element(Name, Static0)    end,    check_module_names(Static, All, "declared 'static'"),    verbose("static modules: ~p.", [Static], Opts),    %% If no modules are explicitly specified as "safe", it is assumed    %% that *all* source modules are "safe" except the target module and    %% those explicitly specified as "static".    Safe = case proplists:is_defined(safe, Opts) of	       false ->		   ordsets:subtract(Sources,				    ordsets:add_element(Name, Static0));	       true ->		   ordsets:from_list(		     proplists:append_values(safe, Opts))	   end,    check_module_names(Safe, All, "declared 'safe'"),    verbose("safe modules: ~p.", [Safe], Opts),    Preserved = (ordsets:is_element(Name, Sources)		 and ordsets:is_element(Name, Export))	or proplists:get_bool(no_banner, Opts),    NoHeaders = proplists:get_bool(no_headers, Opts),    Notes = proplists:get_value(notes, Opts, always),    Rs = proplists:append_values(redirect, Opts),    Redirect = case is_atom_map(Rs) of		   true ->		       Ms = ordsets:from_list([M || {M, _} <- Rs]),		       case ordsets:intersection(Sources, Ms) of			   [] ->			       ok;			   Ms1 ->			       report_error("cannot redirect calls to "					    "modules in input set: ~p.",					    [Ms1]),			       exit(error)		       end,		       dict:from_list(Rs);		   false ->		       report_error("bad value for `redirect' option: "				    "~P.",				    [Rs, 10]),		       exit(error)	       end,    NoImports = case proplists:get_bool(no_imports, Opts) of		    true ->			ordsets:from_list(Sources ++					  dict:fetch_keys(Redirect));		    false ->			ordsets:from_list(dict:fetch_keys(Redirect))		end,    Env = #merge{target = Name,		 sources = Sources,		 export = Export,		 safe = Safe,		 static = Static,		 preserved = Preserved,		 no_headers = NoHeaders,		 notes = Notes,		 redirect = Redirect,		 no_imports = NoImports,		 options = Opts},    merge_sources_2(Env, Modules, Trees, Opts).is_atom_map([{A1, A2} | As]) when is_atom(A1), is_atom(A2) ->    is_atom_map(As);is_atom_map([]) ->    true;is_atom_map(_) ->    false.check_module_names(Names, Sources, Txt) ->    case Names -- Sources of	[] ->	    ok;	Xs ->	    report_error("unknown modules ~s: ~p.", [Txt, Xs]),	    exit(error)    end.%% This function performs all the stages of the actual merge:merge_sources_2(Env, Modules, Trees, Opts) ->    %% Compute the merged name space and the list of renamings.    {Names, Renaming} = merge_namespaces(Modules, Env),        %% Merge the source module descriptions, computing a structure    %% describing the resulting module, and a table of aliases which    %% must be expanded.    {Module, Expansions} = merge_info(Modules, Names, Renaming,				      Env),        %% Merge the actual source code, also returning the "original    %% header" (for the first code section in the output).    St = #state{export = sets:new()},    {Tree, Header, St1} = merge_code(Trees, Modules, Expansions,				     Renaming, Env, St),    %% Filter out unwanted program forms and add a preamble to the code,    %% making a complete module.    Tree1 = erl_syntax:form_list([make_preamble(Module, Header,						Env, St1),				  filter_forms(Tree, Env)]),        %% Tidy the final syntax tree (removing unused functions) and return    %% it together with the list of stub descriptors.    {tidy(Tree1, Opts), make_stubs(Modules, Renaming, Env)}.make_preamble(Module, Header, Env, St) ->    Name = Module#module.name,    Vars = Module#module.vars,    Extras = ordsets:from_list(sets:to_list(St#state.export)),    Exports = make_exports(Module#module.exports, Extras),    Imports = make_imports(Module#module.aliases),    Attributes = make_attributes(Module#module.attributes),    erl_syntax:form_list(module_header(Header, Name, Vars, Env)			 ++ Exports			 ++ Imports			 ++ Attributes).%% If the target preserves one of the source modules, we do not generate%% a new header, but use the original.module_header(Forms, Name, Vars, Env) ->    case Env#merge.preserved of	true ->	    update_header(Forms, Name, Vars);	false ->	    [comment([?COMMENT_BAR,		      "This module was formed by merging "		      "the following modules:",		      ""]		     ++ [lists:flatten(io_lib:fwrite("\t\t`~w'",						     [M]))			 || M <- Env#merge.sources]		     ++ ["",			 timestamp(),			 ""]),	     erl_syntax:attribute(erl_syntax:atom('module'),				  [erl_syntax:atom(Name)])]    end.update_header(Fs, Name, Vars) ->    [M | Fs1] = lists:reverse(Fs),    Ps = if Vars == none -> [];	    true -> [erl_syntax:list([erl_syntax:variable(V)				      || V <- Vars])]	 end,    M1 = rewrite(M, erl_syntax:attribute(erl_syntax:atom('module'),					 [erl_syntax:atom(Name) | Ps])),    lists:reverse([M1 | Fs1]).%% Some functions may have been noted as necessary to export (because of%% how they are called) even though the user did not specify that the%% modules in which these functions originated should be part of the%% interface of the resulting module.make_exports(Exports, Extras) ->    case ordsets:subtract(Extras, Exports) of	[] ->	    [make_export(Exports)];	Es ->	    [make_export(Exports),	     comment(["** The following exports "		      "are not official: **"]),	     make_export(Es)]    end.make_export(Names) ->    Es = [erl_syntax:arity_qualifier(erl_syntax:atom(F),				     erl_syntax:integer(A))	  || {F, A} <- Names],    if Es == [] ->	    comment(["** Nothing is officially exported "		    "from this module! **"]);       true ->	    erl_syntax:attribute(erl_syntax:atom('export'),				 [erl_syntax:list(Es)])    end.%% Any aliases that cannot be expressed using `import' (i.e. those not%% on the form `{F, {M, F}}') are ignored.make_imports(As) ->    %% First remove any auto-imports and "non-proper" imports from    %% the list.    As1 = [A || {F, {_M, F}} = A <- As, not is_auto_import(F)],    [make_import(M, Fs) || {M, Fs} <- group_imports(As1)].make_import(Module, Names) ->    Is = [erl_syntax:arity_qualifier(erl_syntax:atom(F),				     erl_syntax:integer(A))	  || {F, A} <- Names],    erl_syntax:attribute(erl_syntax:atom('import'),			 [erl_syntax:atom(Module),			  erl_syntax:list(Is)]).%% Group aliases by module.group_imports(Imports) ->    dict:to_list(      lists:foldl(	fun ({F, {M, F}}, D) ->		case dict:find(M, D) of		    {ok, V} ->			V1 = ordsets:add_element(F, V),			dict:store(M, V1, D);		    error ->			dict:store(M, [F], D)		end	end,	dict:new(), Imports)).%% ---------------------------------------------------------------------%% Making stub descriptors%%%% These are generated for all exported modules that are not the target%% module.make_stubs(Modules, Renaming, Env) ->    make_stubs_1(Modules, Renaming, Env).make_stubs_1([M | Ms], Renaming, Env) ->    Name = M#module.name,    if Name /= Env#merge.target ->	    case ordsets:is_element(Name, Env#merge.export) of		true ->		    [make_stub(M, Renaming(Name), Env)		     | make_stubs_1(Ms, Renaming, Env)];		false ->		    make_stubs_1(Ms, Renaming, Env)	    end;       true ->	    make_stubs_1(Ms, Renaming, Env)    end;make_stubs_1([], _, _) ->    [].make_stub(M, Map, Env) ->    Target = Env#merge.target,    Es = [{F, {Target, Map(F)}} || F <- M#module.exports],    {M#module.name, Es, M#module.attributes}.%% ---------------------------------------------------------------------%% Removing and/or out-commenting program forms. The returned form%% sequence tree is not necessarily flat.-record(filter, {records, file_attributes, attributes}).filter_forms(Tree, Env) ->    Forms = erl_syntax:form_list_elements(	      erl_syntax:flatten_form_list(Tree)),    erl_syntax:form_list(filter_forms_1(Forms, Env)).filter_forms_1(Forms, Env) ->    {Fs, _} = filter_forms_2(Forms, Env),    lists:reverse(Fs).filter_forms_2(Forms, Env) ->    FileAttrsOpt = proplists:get_value(file_attributes,				       Env#merge.options, comment),    %% Sanity check and translation of option value:    FileAttrs = case FileAttrsOpt of		    yes -> keep;		    no -> delete;		    comment -> kill;		    _ ->			report_error("invalid value for option "				     "`file_attributes': ~w.",				     [FileAttrsOpt]),			exit(error)		end,    Attrs = if length(Env#merge.sources) =:= 1 ->		    delete;    %% keeping the originals looks weird	       true ->		    kill	    end,    S = #filter{records = sets:new(),		file_attributes = FileAttrs,		attributes = Attrs},    lists:foldl(      fun (F, {Fs, S0}) ->	      case filter_form(F, S0) of		  {keep, S1} ->		      {[F | Fs], S1};    % keep		  {kill, S1} ->		      {[kill_form(F) | Fs], S1};    % kill		  {delete, S1} ->		      %% Remove, or kill if it has comments (only		      %% top-level comments are examined).		      case erl_syntax:has_comments(F) of			  false ->			      {Fs, S1};			  true ->			      {[kill_form(F) | Fs], S1}		      end	      end      end,      {[], S}, Forms).filter_form(F, S) ->    case erl_syntax_lib:analyze_form(F) of	{attribute, {'file', _}} ->	    {S#filter.file_attributes, S};	{attribute, {'module', _}} ->	    {delete, S};	{attribute, {'export', _}} ->	    {delete, S};	{attribute, {'import', _}} ->	    {delete, S};	{attribute, {'record', {R, _}}} ->	    Records = S#filter.records,	    case sets:is_element(R, Records) of		true ->		    {kill, S};    % already defined above		false ->		    S1 = S#filter{records =				  sets:add_element(R, Records)},		    {keep, S1}	    end;	{attribute, preprocessor} ->	    {keep, S};    %% keep all preprocessor attributes	{attribute, _} ->	    {S#filter.attributes, S};    %% handle all other attributes	{error_marker, _} ->	    {delete, S};	{warning_marker, _} ->	    {delete, S};	eof_marker ->	    {delete, S};    % these must be deleted!	_ ->	    {keep, S}    % keep all other Erlang forms    end.%% This out-comments (kills) a program form. Any top-level pre-comments%% are moved out, to avoid "nested" comments.kill_form(F) ->    F1 = erl_syntax:set_precomments(F, []),    F2 = erl_syntax_lib:to_comment(F1, ?KILL_PREFIX),    erl_syntax:set_precomments(F2,			       erl_syntax:get_precomments(F)).%% ---------------------------------------------------------------------%% Merging the name spaces of a set of modules. Returns the final set%% (see module `sets') of names and a total renaming function (atom())%% -> ({atom(), integer()}) -> {atom(), integer()}.%%%% Names are added in two passes, in order to avoid renaming the%% interface functions whenever possible: all exported functions are%% added to the name space before any nonexported are added, and%% "exported" modules are taken before any other. Thus, the order is:%%%%   - exported functions of exported modules%%   - exported functions of nonexported modules%%   - internal functions of exported modules%%   - internal functions of nonexported modules%%%% In fact, only the first group is important, but there might be some%% point in establishing the above order, for better readability of the%% final code.merge_namespaces(Modules, Env) ->    Export = Env#merge.export,

⌨️ 快捷键说明

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