asn1ct_gen.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,973 行 · 第 1/4 页

ERL
1,973
字号
	    Name = list2name([T,check]),	    emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),	    %% insert in ets table and do look ahead check	    Typedef = asn1_db:dbget(M,T),	    RefType = Typedef#typedef.typespec,	    InType = asn1ct_gen:get_inner(RefType#type.def),	    case insert_once(check_functions,{Name,RefType}) of		true ->		    lookahead_innertype([T],InType,RefType);%		    case asn1ct_gen:type(InType) of%			{constructed,bif} ->%			    lookahead_innertype([T],InType,RefType);%			#'Externaltypereference'{type=TNew} ->%			    lookahead_innertype([TNew],InType,RefType);%			_ ->%			    ok%		    end;		_ ->		    ok	    end;	{constructed,bif} ->	    NameList = [Cname|TopType],	    Name = list2name(NameList ++ [check]),	    emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),	    ets:insert(check_functions,{Name,Type}),	    %% Must look for check functions in InnerType,	    %% that may be referenced  or internal defined 	    %% constructed types not used elsewhere.	    lookahead_innertype(NameList,InnerType,Type)    end.gen_prim_check_call(PrimType,DefaultValue,Element,Type) ->    case unify_if_string(PrimType) of	'BOOLEAN' ->	    emit({"asn1rt_check:check_bool(",DefaultValue,", ",		  Element,")"});	'INTEGER' ->	    NNL =		case Type#type.def of		    {_,NamedNumberList} -> NamedNumberList;		    _ -> []		end,	    emit({"asn1rt_check:check_int(",DefaultValue,", ",		  Element,", ",{asis,NNL},")"});	'BIT STRING' ->	    {_,NBL} = Type#type.def,	    emit({"asn1rt_check:check_bitstring(",DefaultValue,", ",		  Element,", ",{asis,NBL},")"});	'OCTET STRING' ->	    emit({"asn1rt_check:check_octetstring(",DefaultValue,", ",		  Element,")"});	'NULL' ->	    emit({"asn1rt_check:check_null(",DefaultValue,", ",		  Element,")"});	'OBJECT IDENTIFIER' ->	    emit({"asn1rt_check:check_objectidentifier(",DefaultValue,		  ", ",Element,")"});	'ObjectDescriptor' ->	    emit({"asn1rt_check:check_objectdescriptor(",DefaultValue,		  ", ",Element,")"});	'REAL' ->	    emit({"asn1rt_check:check_real(",DefaultValue,		  ", ",Element,")"});	'ENUMERATED' ->	    {_,Enumerations} = Type#type.def,	    emit({"asn1rt_check:check_enum(",DefaultValue,		  ", ",Element,", ",{asis,Enumerations},")"});	restrictedstring ->	    emit({"asn1rt_check:check_restrictedstring(",DefaultValue,		  ", ",Element,")"})    end.%% lokahead_innertype/3 traverses Type and checks if check functions%% have to be generated, i.e. for all constructed or referenced types.lookahead_innertype(Name,'SEQUENCE',Type) ->    Components = (Type#type.def)#'SEQUENCE'.components,    lookahead_components(Name,Components);lookahead_innertype(Name,'SET',Type) ->    Components = (Type#type.def)#'SET'.components,    lookahead_components(Name,Components);lookahead_innertype(Name,'CHOICE',Type) ->    {_,Components} = Type#type.def,    lookahead_components(Name,Components);lookahead_innertype(Name,'SEQUENCE OF',SeqOf) ->    lookahead_sof(Name,'SEQOF',SeqOf);lookahead_innertype(Name,'SET OF',SeqOf) ->    lookahead_sof(Name,'SETOF',SeqOf);lookahead_innertype(_Name,#'Externaltypereference'{module=M,type=T},_) ->    Typedef = asn1_db:dbget(M,T),    RefType = Typedef#typedef.typespec,    InType = asn1ct_gen:get_inner(RefType#type.def),    case type(InType) of	{constructed,bif} ->	    NewName = list2name([T,check]),	    case insert_once(check_functions,{NewName,RefType}) of		true ->		    lookahead_innertype([T],InType,RefType);		_ ->		    ok	    end;	#'Externaltypereference'{} ->	    NewName = list2name([T,check]),	    case insert_once(check_functions,{NewName,RefType}) of		true ->		    lookahead_innertype([T],InType,RefType);		_ ->		    ok	    end;	_ ->	    ok    end;%    case insert_once(check_functions,{list2name(Name++[check]),Type}) of%	true ->%	    InnerType = asn1ct_gen:get_inner(Type#type.def),%	    case asn1ct_gen:type(InnerType) of%		{constructed,bif} ->%		    lookahead_innertype([T],InnerType,Type);%		#'Externaltypereference'{type=TNew} ->%		    lookahead_innertype([TNew],InnerType,Type);%		_ ->%		    ok%	    end;%	_ ->%	    ok%    end;lookahead_innertype(_,_,_) ->    ok.lookahead_components(_,[]) -> ok;lookahead_components(Name,[C|Cs]) ->    #'ComponentType'{name=Cname,typespec=Type} = C,    InType = asn1ct_gen:get_inner(Type#type.def),    case asn1ct_gen:type(InType) of	{constructed,bif} ->	    case insert_once(check_functions,			     {list2name([Cname|Name] ++ [check]),Type}) of		true ->		    lookahead_innertype([Cname|Name],InType,Type);		_ ->		    ok	    end;	#'Externaltypereference'{module=RefMod,type=RefName} ->	    Typedef = asn1_db:dbget(RefMod,RefName),	    RefType = Typedef#typedef.typespec,	    case insert_once(check_functions,{list2name([RefName,check]),					      RefType}) of		true ->		    lookahead_innertype([RefName],InType,RefType);		_ ->		    ok	    end;	_ ->	    ok    end,    lookahead_components(Name,Cs).lookahead_sof(Name,SOF,SOFType) ->    Type = case SOFType#type.def of	       {_,_Type} -> _Type;	       _Type -> _Type	   end,    InnerType = asn1ct_gen:get_inner(Type#type.def),    case asn1ct_gen:type(InnerType) of	{constructed,bif} ->	    %% this is if a constructed type is defined in	    %% the SEQUENCE OF type	    NameList = [SOF|Name],	    insert_once(check_functions,			{list2name(NameList ++ [check]),Type}),	    lookahead_innertype(NameList,InnerType,Type);	#'Externaltypereference'{module=M,type=T} ->	    Typedef = asn1_db:dbget(M,T),	    RefType = Typedef#typedef.typespec,	    InType = get_inner(RefType#type.def),	    case insert_once(check_functions,			     {list2name([T,check]),RefType}) of		true ->		    lookahead_innertype([T],InType,RefType);		_ ->		    ok	    end;	_ ->	    ok    end.insert_once(Table,Object) ->    case ets:lookup(Table,element(1,Object)) of	[] ->	    ets:insert(Table,Object); %returns true	_ -> false    end.unify_if_string(PrimType) ->    case PrimType of	'NumericString' ->	    restrictedstring;	'PrintableString' ->	    restrictedstring;	'TeletexString' ->	    restrictedstring;	'VideotexString' ->	    restrictedstring;	'IA5String' ->	    restrictedstring;	'UTCTime' ->	    restrictedstring;	'GeneralizedTime' ->	    restrictedstring;	'GraphicString' ->	    restrictedstring;	'VisibleString' ->	    restrictedstring;	'GeneralString' ->	    restrictedstring;	'UniversalString' ->	    restrictedstring;	'BMPString' ->	    restrictedstring;	'UTF8String' ->	    restrictedstring;	Other -> Other    end.		get_inner(A) when atom(A) -> A;    get_inner(Ext) when record(Ext,'Externaltypereference') -> Ext;    get_inner(Tref) when record(Tref,typereference) -> Tref;get_inner({fixedtypevaluefield,_,Type}) ->    if 	record(Type,type) ->	    get_inner(Type#type.def);	true ->	    get_inner(Type)    end;get_inner({typefield,TypeName}) ->    TypeName;get_inner(#'ObjectClassFieldType'{type=Type}) ->%    get_inner(Type);    Type;get_inner(T) when tuple(T) ->     case element(1,T) of	Tuple when tuple(Tuple),element(1,Tuple) == objectclass ->	    case catch(lists:last(element(2,T))) of		{valuefieldreference,FieldName} ->		    get_fieldtype(element(2,Tuple),FieldName);		{typefieldreference,FieldName} ->		    get_fieldtype(element(2,Tuple),FieldName);		{'EXIT',Reason} ->		    throw({asn1,{'internal error in get_inner/1',Reason}})	    end;	_ -> element(1,T)    end.type(X) when record(X,'Externaltypereference') ->    X;type(X) when record(X,typereference) ->    X;type('ASN1_OPEN_TYPE') ->    'ASN1_OPEN_TYPE';type({fixedtypevaluefield,_Name,Type}) when record(Type,type) ->    type(get_inner(Type#type.def));type({typefield,_}) ->    'ASN1_OPEN_TYPE';type(X) ->    %%    io:format("asn1_types:type(~p)~n",[X]),    case catch type2(X) of	{'EXIT',_} ->	    {notype,X};	Normal ->	    Normal    end.type2(X) ->    case prim_bif(X) of	true ->	    {primitive,bif};	false ->	    case construct_bif(X) of		true ->		    {constructed,bif};		false ->		    {undefined,user}	    end    end.prim_bif(X) ->    lists:member(X,['INTEGER' ,		    'ENUMERATED',		    'OBJECT IDENTIFIER',		    'ANY',		    'NULL',		    'BIT STRING' ,		    'OCTET STRING' ,		    'ObjectDescriptor',		    'NumericString',		    'TeletexString',		    'VideotexString',		    'UTCTime',		    'GeneralizedTime',		    'GraphicString',		    'VisibleString',		    'GeneralString',		    'PrintableString',		    'IA5String',		    'UniversalString',		    'UTF8String',		    'BMPString',		    'ENUMERATED',		    'BOOLEAN']).construct_bif(T) ->    lists:member(T,['SEQUENCE' ,		    'SEQUENCE OF' ,		    'CHOICE' ,		    'SET' ,		    'SET OF']).def_to_tag(#tag{class=Class,number=Number}) ->    {Class,Number};def_to_tag(#'ObjectClassFieldType'{type=Type}) ->    case Type of       T when tuple(T),element(1,T)==fixedtypevaluefield ->	   {'UNIVERSAL',get_inner(Type)};       _ ->	   []   end;def_to_tag(Def) ->    {'UNIVERSAL',get_inner(Def)}.    %% Information Object Classtype_from_object(X) ->    case (catch lists:last(element(2,X))) of	{'EXIT',_} ->	    {notype,X};	Normal ->	    Normal    end.get_fieldtype([],_FieldName)->    {no_type,no_name};get_fieldtype([Field|Rest],FieldName) ->    case element(2,Field) of	FieldName ->	    case element(1,Field) of		fixedtypevaluefield ->		    {element(1,Field),FieldName,element(3,Field)};		_ ->		    {element(1,Field),FieldName}	    end;	_  ->	    get_fieldtype(Rest,FieldName)    end.get_fieldcategory([],_FieldName) ->    no_cat;get_fieldcategory([Field|Rest],FieldName) ->    case element(2,Field) of	FieldName ->	    element(1,Field);	_ ->	    get_fieldcategory(Rest,FieldName)    end.get_typefromobject(Type) when record(Type,type) ->    case Type#type.def of	{{objectclass,_,_},TypeFrObj} when list(TypeFrObj) ->	    {_,FieldName} = lists:last(TypeFrObj),	    FieldName;	_ ->	    {no_field}    end.get_classfieldcategory(Type,FieldName) ->    case (catch Type#type.def) of	{{obejctclass,Fields,_},_} ->	    get_fieldcategory(Fields,FieldName);	{'EXIT',_} ->	    no_cat;	_ ->	    no_cat    end.%% Information Object Class%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Convert a list of name parts to something that can be output by emit%% %% used to output function names in generated code.list2name(L) ->    NewL = list2name1(L),    lists:concat(lists:reverse(NewL)).list2name1([{ptype,H1},H2|T]) ->    [H1,"_",list2name([H2|T])];list2name1([H1,H2|T]) ->    [H1,"_",list2name([H2|T])];list2name1([{ptype,H}|_T]) ->    [H];list2name1([H|_T]) ->    [H];list2name1([]) ->    [].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Convert a list of name parts to something that can be output by emit%% stops at {ptype,Pname} i.e Pname whill be the first part of the name%% used to output record names in generated code.list2rname(L) ->    NewL = list2rname1(L),    lists:concat(lists:reverse(NewL)).list2rname1([{ptype,H1},_H2|_T]) ->    [H1];list2rname1([H1,H2|T]) ->    [H1,"_",list2name([H2|T])];list2rname1([{ptype,H}|_T]) ->    [H];list2rname1([H|_T]) ->    [H];list2rname1([]) ->    [].constructed_suffix(_,#'SEQUENCE'{pname=Ptypename}) when Ptypename =/= false ->    {ptype, Ptypename};constructed_suffix(_,#'SET'{pname=Ptypename}) when Ptypename =/= false ->    {ptype,Ptypename};constructed_suffix('SEQUENCE OF',_) ->     'SEQOF';constructed_suffix('SET OF',_) ->     'SETOF'.erule(ber) ->    ber;erule(ber_bin) ->    ber;erule(ber_bin_v2) ->    ber_bin_v2;erule(per) ->    per;erule(per_bin) ->    per.wrap_ber(ber) ->    ber_bin;wrap_ber(Erule) ->    Erule.rt2ct_suffix() ->    Options = get(encoding_options),    case {lists:member(optimize,Options),lists:member(per_bin,Options)} of	{true,true} -> "_rt2ct";	_ -> ""    end.rt2ct_suffix(per_bin) ->    Options = get(encoding_options),    case lists:member(optimize,Options) of	true -> "_rt2ct";	_ -> ""    end;rt2ct_suffix(_) -> "".index2suffix(0) ->    "";index2suffix(N) ->    lists:concat(["_",N]).get_constraint(C,Key) ->    case lists:keysearch(Key,1,C) of	false ->	     no;	{value,{_,V}} -> 	    V;	{value,Cnstr} ->	    Cnstr    end.

⌨️ 快捷键说明

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