ic_pragma.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,956 行 · 第 1/4 页
ERL
1,956 行
%% Finds out which pragma PREFIX that affects %% the scope Scopepragma_prefix(G,Scope,Object) -> pragma_prefix_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).%% Finds out which pragma PREFIX that affects %% the scope Scopepragma_prefix_cover(PragmaTab,Name,Scope,LineNr) -> case lookup(PragmaTab,prefix) of [] -> none; PragmaPrefixList -> FilteredPragmaPrefixList = filter_pragma_prefix_list(PragmaTab,Name,Scope,PragmaPrefixList), case most_local(FilteredPragmaPrefixList,Scope) of [] -> none; MostLocalList -> case dominant_prefix(MostLocalList,LineNr) of none -> none; %% Just filter empty pragma prefix {prefix,{pragma,{_,_,_},_,{'<string_literal>',_,[]}},_,_,_,_} -> none; DP -> %% Return the scoped id (reversed list of %% path elements, but remember to remove %% '[]' that represents the top level slashify(lists:sublist(Scope, 1, length(Scope) - length(element(4,DP))) ++ [ element(3,element(4,element(2,DP)))]) end end end.%% Returns a slashified name, [I1, M1] becomes "M1/I1"slashify(List) -> lists:foldl(fun(X, Acc) -> X++"/"++Acc end, hd(List), tl(List)).%% Finds out which pragma VERSION that affects %% the scope Scopepragma_version(G,Scope,Object) -> pragma_version_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).%% Finds out which pragma VERSION that affects %% the scope Scopepragma_version_cover(PragmaTab,Name,Scope,LineNr) -> case lookup(PragmaTab,version) of [] -> default_version(); PragmaVersionList -> case all_actual_for_version_or_id( PragmaVersionList, Name ) of [] -> default_version(); ActualVersionList -> case most_local(ActualVersionList,Scope) of [] -> default_version(); MostLocalList -> case dominant_version(MostLocalList,LineNr) of DV -> element(4,element(2,DV)) end end end end.default_version() -> "1.0". %% Finds out which pragma ID that affects %% the scope Scopepragma_id(G,Scope,Object) -> pragma_id_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).%% Finds out which pragma ID that affects %% the scope Scopepragma_id_cover(PragmaTab,Name,Scope,LineNr) -> case lookup(PragmaTab,id) of [] -> none; PragmaIdList -> case all_actual_for_version_or_id( PragmaIdList, Name ) of [] -> none; ActualIdList -> case most_local(ActualIdList,Scope) of [] -> none; MostLocalList -> case dominant_id(MostLocalList,LineNr) of PI -> element(3,element(4,element(2,PI))) end end end end. %% Finds out which pragma VERSION ( or ID ) that %% that affects the scope object with name NAMEall_actual_for_version_or_id(NList, Name) -> all_actual_for_version_or_id( NList, [], Name ).all_actual_for_version_or_id([], Actual, _) -> Actual;all_actual_for_version_or_id([First|Rest], Found, Name) -> case is_actual_for_version_or_id(First,Name) of true -> all_actual_for_version_or_id(Rest, [First|Found], Name); false -> all_actual_for_version_or_id(Rest, Found, Name) end.is_actual_for_version_or_id( Current, Name ) -> case element(3,element(3,element(2,Current))) of Name -> true; OtherName -> suffix([Name],tokens(OtherName,"::")) end.%% Find the most locally defind pragmas%% to the scope SCOPEmost_local( SList, Scope ) -> case SList of [] -> []; [First|Rest] -> case suffix( element(4,First), Scope ) of true -> most_local( Rest, First, Scope, [First] ); false -> most_local( Rest, Scope ) end end.%% Returns a list of all pragmas found in the %% same scope. Should choose the right one by looking %% att the position of the pragma in relation to%% the current object..... ( For hairy cases ). most_local( SList, Current, Scope, AllFound ) -> case SList of [] -> AllFound; [First|Rest] -> FirstScope = element(4,First), case suffix( FirstScope, Scope ) of true -> CurrentScope = element(4,Current), case suffix( CurrentScope, FirstScope ) of true -> case length( CurrentScope ) == length( FirstScope ) of true -> %% SAME SCOPE ! KEEP BOTH most_local( Rest, Current, Scope, [First|AllFound] ); false -> most_local( Rest, First, Scope, [First] ) end; false -> most_local( Rest, Current, Scope, AllFound ) end; false -> most_local( Rest, Current, Scope, AllFound ) end end.%% Find the most dominant prefix pragmas%% located onto the SAME scope. Now%% we look att the line number, the position%% on the file. dominant_prefix(SList,LineNr) -> case SList of [First|Rest] -> dominant_prefix(Rest,First,LineNr) end.dominant_prefix([],{prefix,X,PLNr,N,F,T},LineNr) -> case LineNr > PLNr of true -> {prefix,X,PLNr,N,F,T}; false -> none end;dominant_prefix([{prefix,FX,FPLNr,FN,F1,T1}|Rest],{prefix,CX,CPLNr,CN,F2,T2},LineNr) -> case LineNr > FPLNr of % Check if FIRST before the object true -> case FPLNr > CPLNr of % Check if FIRST after CURRENT true -> dominant_prefix(Rest,{prefix,FX,FPLNr,FN,F1,T1},LineNr); false -> dominant_prefix(Rest,{prefix,CX,CPLNr,CN,F2,T2},LineNr) end; false -> % FIRST does not affect the object dominant_prefix(Rest,{prefix,CX,CPLNr,CN,F2,T2},LineNr) end.%% Find the most dominant version pragmas%% located onto the SAME scope. Now%% we look att the line number, the position%% on the file. dominant_version(SList,LineNr) -> case SList of [First|Rest] -> dominant_version(Rest,First,LineNr) end.dominant_version([],Current,_) -> Current;dominant_version([{version,FX,FPLNr,FN,F1,T1}|Rest],{version,CX,CPLNr,CN,F2,T2},LineNr) -> case FPLNr > CPLNr of % Check if FIRST after CURRENT true -> dominant_version(Rest,{prefix,FX,FPLNr,FN,F1,T1},LineNr); false -> dominant_version(Rest,{prefix,CX,CPLNr,CN,F2,T2},LineNr) end.%% Find the most dominant id pragmas%% located onto the SAME scope. Now%% we look att the line number, the position%% on the file. dominant_id(SList,LineNr) -> case SList of [First|Rest] -> dominant_id(Rest,First,LineNr) end.dominant_id([],Current,_) -> Current;dominant_id([{id,FX,FPLNr,FN,F1,T1}|Rest],{id,CX,CPLNr,CN,F2,T2},LineNr) -> case FPLNr > CPLNr of % Check if FIRST after CURRENT true -> dominant_id(Rest,{id,FX,FPLNr,FN,F1,T1},LineNr); false -> dominant_id(Rest,{id,CX,CPLNr,CN,F2,T2},LineNr) end.%% This registers a module defined inside the file or%% an included file. A tuple that describes the module%% is added to the table. %% Observe that the modules registered are ONLY those%% who are in the top level, not definedd inside others !mk_ref(G,Name,Type) -> case length(Name) > 1 of true -> %% The interface is NOT defined att top level true; false -> S = ic_genobj:pragmatab(G), File = get_idlfile(S), % The current file or an included one. case idlfile(G) of % The current file to be compiled. File -> insert(S,{Type,Name,File,local}); _ -> insert(S,{Type,Name,File,included}) end end.%% The same as mk_ref/3 but this registers everything with %% all vital information available inside files.%% Registers ESSENTIAL data for included filesmk_file_data(G,X,Scope,Type) -> S = ic_genobj:pragmatab(G), Name = get_id2(X), PreprocFile = get_idlfile(S), % The current file or an included one. CompFile = idlfile(G), % The current file compiled Depth = length(Scope), % The depth of the scope ScopedName = ic_util:to_undersc([Name|Scope]), Line = ic_forms:get_line(X), case PreprocFile of CompFile -> insert(S,{file_data_local,CompFile,CompFile,Type,Scope,Name,ScopedName,Depth,Line}); PreprocFile -> insert(S,{file_data_included,PreprocFile,CompFile,Type,Scope,Name,ScopedName,Depth,Line}) end.%% Return a list with all the headers from%% the local file that represent the module%% or interface that is preciding the currentget_local_c_headers(G,X) -> S = ic_genobj:pragmatab(G), Local = lookup(S,file_data_local), FoundLocal = get_local_c_headers(X,Local,Local), no_doubles(FoundLocal).get_local_c_headers(X,Local,Local) -> get_local_c_headers(X,Local,Local,[]).get_local_c_headers(_X,[],_All,Found) -> Found;get_local_c_headers(X,[{file_data_local,_PF_idl,_,module,_,_,SN,_,Line}|Hs],All,Found)-> case ic_forms:get_line(X) > Line of true -> get_local_c_headers(X,Hs,All,[SN|Found]); false -> get_local_c_headers(X,Hs,All,Found) end;get_local_c_headers(X,[{file_data_local,_PF_idl,_,interface,_,_,SN,_,Line}|Hs],All,Found)-> case ic_forms:get_line(X) > Line of true -> get_local_c_headers(X,Hs,All,[SN|Found]); false -> get_local_c_headers(X,Hs,All,Found) end;get_local_c_headers(X,[_|Hs],All,Found) -> get_local_c_headers(X,Hs,All,Found).%% Return a list with all the headers from%% the included file that represent the module%% or interface that have to be includedget_included_c_headers(G) -> S = ic_genobj:pragmatab(G), Included = lookup(S,file_data_included), FoundIncluded = get_included_c_headers(Included,Included), no_doubles(FoundIncluded).get_included_c_headers(Included,Included) -> get_included_c_headers(Included,Included,[]).get_included_c_headers([],_All,Found) -> Found;get_included_c_headers([{file_data_included,PF_idl,_CF_idl,T,_S,_N,SN,0,_}|Hs],All,Found) -> Len = length(PF_idl), FN = string:sub_string(PF_idl,1,Len-4), case only_top_level(PF_idl,All) of true -> %% L = string:tokens(FN,"/"), FN2 = lists:last(L), %% get_included_c_headers(Hs,All,["oe_"++FN2|Found]); false -> case T of module -> case contains_interface(PF_idl,All) of true -> %% L = string:tokens(FN,"/"), FN2 = lists:last(L), %% get_included_c_headers(Hs,All,["oe_"++FN2|Found]); false -> get_included_c_headers(Hs,All,[SN|Found]) end; interface -> case contains_interface(PF_idl,All) of true -> %% L = string:tokens(FN,"/"), FN2 = lists:last(L), %% get_included_c_headers(Hs,All,["oe_"++FN2|Found]); false -> get_included_c_headers(Hs,All,[SN|Found]) end; _ -> get_included_c_headers(Hs,All,["oe_"++FN|Found]) end end;get_included_c_headers([{file_data_included,_PF_idl,_,module,_,_,SN,_,_}|Hs],All,Found)-> get_included_c_headers(Hs,All,[SN|Found]);get_included_c_headers([{file_data_included,_PF_idl,_,interface,_,_,SN,_,_}|Hs],All,Found)-> get_included_c_headers(Hs,All,[SN|Found]);get_included_c_headers([_|Hs],All,Found) -> get_included_c_headers(Hs,All,Found).%% Help functions for the aboveonly_top_level(_PF_idl,[]) -> true;only_top_level(PF_idl,[H|Hs]) -> case element(2,H) of PF_idl -> case element(8,H) > 0 of true -> false; false -> only_top_level(PF_idl,Hs) end; _ -> only_top_level(PF_idl,Hs) end. contains_interface(_PF_idl,[]) -> false;contains_interface(PF_idl,[H|Hs]) -> case element(2,H) of PF_idl -> case element(4,H) of interface -> case element(8,H) > 0 of true -> true; false -> contains_interface(PF_idl,Hs) end; _ -> contains_interface(PF_idl,Hs) end; _ -> contains_interface(PF_idl,Hs) end. %% This returns a list of everything defined in an included file.get_incl_refs(G) -> S = ic_genobj:pragmatab(G), RefList = ets:match(S,{mod_ref,'$0','_',included}) ++ ets:match(S,{ifc_ref,'$0','_',included}) ++ ets:match(S,{const_ref,'$0','_',included}) ++ ets:match(S,{typedef_ref,'$0','_',included}) ++ ets:match(S,{except_ref,'$0','_',included}) ++ ets:match(S,{struct_ref,'$0','_',included}) ++ ets:match(S,{union_ref,'$0','_',included}) ++ ets:match(S,{enum_ref,'$0','_',included}) ++ ets:match(S,{attr_ref,'$0','_',included}), case RefList of [] -> none; _ -> RefList end.%% This returns a list of everything locally defined.get_local_refs(G) -> S = ic_genobj:pragmatab(G), RefList = ets:match(S,{mod_ref,'$0','_',local}) ++ ets:match(S,{ifc_ref,'$0','_',local}) ++ ets:match(S,{const_ref,'$0','_',local}) ++ ets:match(S,{typedef_ref,'$0','_',local}) ++ ets:match(S,{except_ref,'$0','_',local}) ++ ets:match(S,{struct_ref,'$0','_',local}) ++ ets:match(S,{union_ref,'$0','_',local}) ++ ets:match(S,{enum_ref,'$0','_',local}) ++ ets:match(S,{attr_ref,'$0','_',local}), case RefList of [] -> none; _ -> RefList end.%% This is intented to be used for solving the identification%% problem introduced by pragmas. It creates aliases between%% scoped and "final" identities.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?