asn1ct_check.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,941 行 · 第 1/5 页
ERL
1,941 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(asn1ct_check).%% Main Module for ASN.1 compile time functions%-compile(export_all).-export([check/2,storeindb/1]).%-define(debug,1).-include("asn1_records.hrl").%%% The tag-number for universal types-define(N_BOOLEAN, 1). -define(N_INTEGER, 2). -define(N_BIT_STRING, 3).-define(N_OCTET_STRING, 4).-define(N_NULL, 5). -define(N_OBJECT_IDENTIFIER, 6). -define(N_OBJECT_DESCRIPTOR, 7). -define(N_EXTERNAL, 8). % constructed-define(N_INSTANCE_OF,8).-define(N_REAL, 9). -define(N_ENUMERATED, 10). -define(N_EMBEDDED_PDV, 11). % constructed-define(N_UTF8String, 12).-define(N_SEQUENCE, 16). -define(N_SET, 17). -define(N_NumericString, 18).-define(N_PrintableString, 19).-define(N_TeletexString, 20).-define(N_VideotexString, 21).-define(N_IA5String, 22).-define(N_UTCTime, 23). -define(N_GeneralizedTime, 24). -define(N_GraphicString, 25).-define(N_VisibleString, 26).-define(N_GeneralString, 27).-define(N_UniversalString, 28).-define(N_CHARACTER_STRING, 29). % constructed-define(N_BMPString, 30).-define(TAG_PRIMITIVE(Num), case S#state.erule of ber_bin_v2 -> #tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=0}; _ -> [] end).-define(TAG_CONSTRUCTED(Num), case S#state.erule of ber_bin_v2 -> #tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=32}; _ -> [] end).-record(newt,{type=unchanged,tag=unchanged,constraint=unchanged,inlined=no}). % used in check_type to update type and tag-record(newv,{type=unchanged,value=unchanged}). % used in check_value to update type and value check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) -> %%Predicates used to filter errors TupleIs = fun({T,_},T) -> true; (_,_) -> false end, IsClass = fun(X) -> TupleIs(X,asn1_class) end, IsObjSet = fun(X) -> TupleIs(X,objectsetdef) end, IsPObjSet = fun(X) -> TupleIs(X,pobjectsetdef) end, IsObject = fun(X) -> TupleIs(X,objectdef) end, IsValueSet = fun(X) -> TupleIs(X,valueset) end, Element2 = fun(X) -> element(2,X) end, Element1 = fun(X) -> element(1,X) end, %% initialize internal book keeping save_asn1db_uptodate(S,S#state.erule,S#state.mname), _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used %% table to save instances of parameterized objects,object sets asn1ct:create_ets_table(parameterized_objects,[named_table]), Terror = checkt(S,Types,[]), ?dbg("checkt finished with errors:~n~p~n~n",[Terror]), %% get parameterized object sets sent to checkt/3 %% and update Terror {PObjSetNames1,Terror2} = filter_errors(IsPObjSet,Terror), Verror = checkv(S,Values ++ ObjectSets,[]), %value sets may be parsed as object sets ?dbg("checkv finished with errors:~n~p~n~n",[Verror]), %% get information object classes wrongly sent to checkt/3 %% and update Terror2 {AddClasses,Terror3} = filter_errors(IsClass,Terror2), NewClasses = Classes++AddClasses, Cerror = checkc(S,NewClasses,[]), ?dbg("checkc finished with errors:~n~p~n~n",[Cerror]), %% get object sets incorrectly sent to checkv/3 %% and update Verror {ObjSetNames,Verror2} = filter_errors(IsObjSet,Verror), %% get parameterized object sets incorrectly sent to checkv/3 %% and update Verror2 {PObjSetNames,Verror3} = filter_errors(IsPObjSet,Verror2), %% get objects incorrectly sent to checkv/3 %% and update Verror3 {ObjectNames,Verror4} = filter_errors(IsObject,Verror3), NewObjects = Objects++ObjectNames, NewObjectSets = ObjSetNames ++ PObjSetNames ++ PObjSetNames1, %% get value sets %% and update Verror4 {ValueSetNames,Verror5} = filter_errors(IsValueSet,Verror4), asn1ct:create_ets_table(inlined_objects,[named_table]), {Oerror,ExclO,ExclOS} = checko(S,NewObjects ++ NewObjectSets, [],[],[]), ?dbg("checko finished with errors:~n~p~n~n",[Oerror]), InlinedObjTuples = ets:tab2list(inlined_objects), InlinedObjects = lists:map(Element2,InlinedObjTuples), ets:delete(inlined_objects), ParameterizedElems = ets:tab2list(parameterized_objects), ParObjectSets = lists:filter(fun({_OSName,objectset,_}) -> true; (_)-> false end,ParameterizedElems), ParObjectSetNames = lists:map(Element1,ParObjectSets), ParTypes = lists:filter(fun({_TypeName,type,_}) -> true; (_) -> false end, ParameterizedElems), ParTypesNames = lists:map(Element1,ParTypes), ets:delete(parameterized_objects), Exporterror = check_exports(S,S#state.module), case {Terror3,Verror5,Cerror,Oerror,Exporterror} of {[],[],[],[],[]} -> ContextSwitchTs = context_switch_in_spec(), InstanceOf = instance_of_in_spec(S#state.mname), NewTypes = lists:subtract(Types,AddClasses) ++ ContextSwitchTs ++ InstanceOf ++ ParTypesNames, NewValues = lists:subtract(Values,PObjSetNames++ObjectNames++ ValueSetNames), {ok, {NewTypes,NewValues,ParameterizedTypes, NewClasses,NewObjects,NewObjectSets}, {NewTypes,NewValues,ParameterizedTypes,NewClasses, lists:subtract(NewObjects,ExclO)++InlinedObjects, lists:subtract(NewObjectSets,ExclOS)++ParObjectSetNames}}; _ ->{error,{asn1,lists:flatten([Terror3,Verror5,Cerror, Oerror,Exporterror])}} end.context_switch_in_spec() -> L = [{external,'EXTERNAL'}, {embedded_pdv,'EMBEDDED PDV'}, {character_string,'CHARACTER STRING'}], F = fun({T,TName},Acc) -> case get(T) of generate -> erase(T), [TName|Acc]; _ -> Acc end end, lists:foldl(F,[],L).instance_of_in_spec(ModName) -> case get(instance_of) of L when is_list(L) -> case lists:member(ModName,L) of true -> erase(instance_of), ['INSTANCE OF']; _ -> erase(instance_of), [] end; _ -> [] end.instance_of_decl(ModName) -> Mods = get_instance_of(), case lists:member(ModName,Mods) of true -> ok; _ -> put(instance_of,[ModName|Mods]) end.get_instance_of() -> case get(instance_of) of undefined -> []; L -> L end.filter_errors(Pred,ErrorList) -> Element2 = fun(X) -> element(2,X) end, RemovedTupleElements = lists:filter(Pred,ErrorList), RemovedNames = lists:map(Element2,RemovedTupleElements), %% remove value set name tuples from Verror RestErrors = lists:subtract(ErrorList,RemovedTupleElements), {RemovedNames,RestErrors}. check_exports(S,Module = #module{}) -> case Module#module.exports of {exports,[]} -> []; {exports,all} -> []; {exports,ExportList} when list(ExportList) -> IsNotDefined = fun(X) -> case catch get_referenced_type(S,X) of {error,{asn1,_}} -> true; _ -> false end end, case lists:filter(IsNotDefined,ExportList) of [] -> []; NoDefExp -> GetName = fun(T = #'Externaltypereference'{type=N})-> %%{exported,undefined,entity,N} NewS=S#state{type=T,tname=N}, error({export,"exported undefined entity",NewS}) end, lists:map(GetName,NoDefExp) end end. checkt(S,[Name|T],Acc) -> ?dbg("Checking type ~p~n",[Name]), Result = case asn1_db:dbget(S#state.mname,Name) of undefined -> error({type,{internal_error,'???'},S}); Type when record(Type,typedef) -> NewS = S#state{type=Type,tname=Name}, case catch(check_type(NewS,Type,Type#typedef.typespec)) of {error,Reason} -> error({type,Reason,NewS}); {'EXIT',Reason} -> error({type,{internal_error,Reason},NewS}); {asn1_class,_ClassDef} -> {asn1_class,Name}; pobjectsetdef -> {pobjectsetdef,Name}; pvalueset -> {pvalueset,Name}; Ts -> case Type#typedef.checked of true -> % already checked and updated ok; _ -> NewTypeDef = Type#typedef{checked=true,typespec = Ts}, asn1_db:dbput(NewS#state.mname,Name,NewTypeDef), % update the type ok end end end, case Result of ok -> checkt(S,T,Acc); _ -> checkt(S,T,[Result|Acc]) end;checkt(S,[],Acc) -> case check_contextswitchingtypes(S,[]) of [] -> lists:reverse(Acc); L -> checkt(S,L,Acc) end.check_contextswitchingtypes(S,Acc) -> CSTList=[{external,'EXTERNAL'}, {embedded_pdv,'EMBEDDED PDV'}, {character_string,'CHARACTER STRING'}], check_contextswitchingtypes(S,CSTList,Acc).check_contextswitchingtypes(S,[{T,TName}|Ts],Acc) -> case get(T) of unchecked -> put(T,generate), check_contextswitchingtypes(S,Ts,[TName|Acc]); _ -> check_contextswitchingtypes(S,Ts,Acc) end;check_contextswitchingtypes(_,[],Acc) -> Acc.checkv(S,[Name|T],Acc) -> ?dbg("Checking valuedef ~p~n",[Name]), Result = case asn1_db:dbget(S#state.mname,Name) of undefined -> error({value,{internal_error,'???'},S}); Value when record(Value,valuedef); record(Value,typedef); %Value set may be parsed as object set. record(Value,pvaluedef); record(Value,pvaluesetdef) -> NewS = S#state{value=Value}, case catch(check_value(NewS,Value)) of {error,Reason} -> error({value,Reason,NewS}); {'EXIT',Reason} -> error({value,{internal_error,Reason},NewS}); {pobjectsetdef} -> {pobjectsetdef,Name}; {objectsetdef} -> {objectsetdef,Name}; {objectdef} -> %% this is an object, save as typedef #valuedef{checked=C,pos=Pos,name=N,type=Type, value=Def}=Value,% Currmod = S#state.mname,% #type{def=% #'Externaltypereference'{module=Mod,% type=CName}} = Type, ClassName = Type#type.def,% case Mod of% Currmod ->% {objectclassname,CName};% _ ->% {objectclassname,Mod,CName}% end, NewSpec = #'Object'{classname=ClassName, def=Def}, NewDef = #typedef{checked=C,pos=Pos,name=N, typespec=NewSpec}, asn1_db:dbput(NewS#state.mname,Name,NewDef), {objectdef,Name}; {valueset,VSet} -> Pos = asn1ct:get_pos_of_def(Value), CheckedVSDef = #typedef{checked=true,pos=Pos, name=Name,typespec=VSet}, asn1_db:dbput(NewS#state.mname,Name,CheckedVSDef), {valueset,Name}; V -> %% update the valuedef asn1_db:dbput(NewS#state.mname,Name,V), ok end end, case Result of ok -> checkv(S,T,Acc); _ -> checkv(S,T,[Result|Acc]) end;checkv(_S,[],Acc) -> lists:reverse(Acc).checkp(S,[Name|T],Acc) -> %io:format("check_ptypedef:~p~n",[Name]), Result = case asn1_db:dbget(S#state.mname,Name) of undefined -> error({type,{internal_error,'???'},S}); Type when record(Type,ptypedef) -> NewS = S#state{type=Type,tname=Name}, case catch(check_ptype(NewS,Type,Type#ptypedef.typespec)) of {error,Reason} -> error({type,Reason,NewS}); {'EXIT',Reason} -> error({type,{internal_error,Reason},NewS});
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?