asn1ct_gen.erl

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

ERL
1,973
字号
    case Erules of	per ->	    emit(["if_binary2list(B) when is_binary(B) ->",nl,		  "  binary_to_list(B);",nl,		  "if_binary2list(L) -> L.",nl,nl]);	_ ->	    ok    end,    gen_decode_partial_incomplete(Erules),    case Types of	[] -> ok;	_ ->	    case Erules of		ber ->		    gen_dispatcher(Types,"encode_disp","enc_",",[]"),		    gen_dispatcher(Types,"decode_disp","dec_",",mandatory");		ber_bin ->		    gen_dispatcher(Types,"encode_disp","enc_",",[]"),		    gen_dispatcher(Types,"decode_disp","dec_",",mandatory");		ber_bin_v2 ->		    gen_dispatcher(Types,"encode_disp","enc_",""),		    gen_dispatcher(Types,"decode_disp","dec_",""),		    gen_partial_inc_dispatcher();		_PerOrPer_bin -> 		    gen_dispatcher(Types,"encode_disp","enc_",""),		    gen_dispatcher(Types,"decode_disp","dec_",",mandatory")	    end,	    emit([nl])    end,    case Erules of	ber ->	    gen_wrapper();	_ -> ok    end,    emit({nl,nl}).gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;					   Erule==ber_bin_v2 ->    case {asn1ct:read_config_data(partial_incomplete_decode),	  asn1ct:get_gen_state_field(inc_type_pattern)} of	{undefined,_} ->	    ok;	{_,undefined} ->	    ok;	_ ->	    case Erule of		ber_bin_v2 ->		    EmitCaseClauses =			fun() ->				emit(["   {'EXIT',{error,Reason}} ->",nl,				      "      {error,Reason};",nl,				      "    {'EXIT',Reason} ->",nl,				      "      {error,{asn1,Reason}};",nl,				      "    Result ->",nl,				      "      {ok,Result}",nl,				      "  end.",nl,nl])			end,		    emit(["decode_partial_incomplete(Type,Data0,",			  "Pattern) ->",nl]),		    emit(["  {Data,_RestBin} =",nl,			  "    ?RT_BER:decode_primitive_",			  "incomplete(Pattern,Data0),",nl,			  "  case catch decode_partial_inc_disp(Type,",			  "Data) of",nl]),		    EmitCaseClauses(),		    emit(["decode_part(Type,Data0) ->",nl]),		    Driver =			case lists:member(driver,get(encoding_options)) of			    true ->				",driver";			    _ -> ""			end,		    emit(["  case catch decode_inc_disp(Type,element(1,?RT_BER:decode(Data0",Driver,"))) of",nl]),% 			  "  {Data,_RestBin} = ?RT_BER:decode(Data0),",nl,% 			  "  case catch decode_inc_disp(Type,Data) of",nl]),		    EmitCaseClauses();		_ -> ok % add later	    end    end;gen_decode_partial_incomplete(_Erule) ->    ok.gen_partial_inc_dispatcher() ->    case {asn1ct:read_config_data(partial_incomplete_decode),	  asn1ct:get_gen_state_field(inc_type_pattern)} of	{undefined,_} ->	    ok;	{_,undefined} ->	    ok;	{Data1,Data2} ->%	    io:format("partial_incomplete_decode: ~p~ninc_type_pattern: ~p~n",[Data,Data2]),	    gen_partial_inc_dispatcher(Data1,Data2)    end.gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest],TypePattern) ->    TPattern =	case lists:keysearch(FuncName,1,TypePattern) of	    {value,{_,TP}} -> TP;	    _ -> exit({error,{asn1_internal_error,exclusive_decode}})	end,    FuncName2=asn1ct:maybe_rename_function(inc_disp,TopType,TPattern),    TopTypeName =	case asn1ct:maybe_saved_sindex(TopType,TPattern) of	    I when integer(I),I>0 ->		lists:concat([TopType,"_",I]);	    _ ->		atom_to_list(TopType)	end,    emit(["decode_partial_inc_disp('",TopTypeName,"',Data) ->",nl,	  "  ",{asis,list_to_atom(lists:concat(["dec-inc-",FuncName2]))},	  "(Data);",nl]),    gen_partial_inc_dispatcher(Rest,TypePattern);gen_partial_inc_dispatcher([],_) ->    emit(["decode_partial_inc_disp(Type,_Data) ->",nl,	  "  exit({error,{asn1,{undefined_type,Type}}}).",nl]).driver_parameter() ->    Options = get(encoding_options),    case lists:member(driver,Options) of	true ->	    ",driver";	_ -> ""    end.gen_wrapper() ->    emit(["wrap_encode(Bytes) when list(Bytes) ->",nl,	  "   binary_to_list(list_to_binary(Bytes));",nl,	  "wrap_encode(Bytes) when binary(Bytes) ->",nl,	  "   binary_to_list(Bytes);",nl,	  "wrap_encode(Bytes) -> Bytes.",nl,nl]),    emit(["wrap_decode(Bytes) when list(Bytes) ->",nl,	  "   list_to_binary(Bytes);",nl,	  "wrap_decode(Bytes) -> Bytes.",nl]).    gen_dispatcher([F1,F2|T],FuncName,Prefix,ExtraArg) ->	emit([FuncName,"('",F1,"',Data) -> '",Prefix,F1,"'(Data",ExtraArg,")",";",nl]),	gen_dispatcher([F2|T],FuncName,Prefix,ExtraArg);gen_dispatcher([Flast|_T],FuncName,Prefix,ExtraArg) ->	emit([FuncName,"('",Flast,"',Data) -> '",Prefix,Flast,"'(Data",ExtraArg,")",";",nl]),	emit([FuncName,"(","Type",",_Data) -> exit({error,{asn1,{undefined_type,Type}}}).",nl,nl,nl]).pgen_info() ->%%     Options = get(encoding_options),%%     emit({"info() ->",nl,%% 	  "  [{vsn,'",asn1ct:vsn(),"'},",%% 	  "   {module,'",Module,"'},",%% 	  "   {options,",io_lib:format("~p",[Options]),"}].",nl}).    emit(["info() ->",nl,	  "   case ?MODULE:module_info() of",nl,	  "      MI when is_list(MI) ->",nl,	  "         case lists:keysearch(attributes,1,MI) of",nl,	  "            {value,{_,Attributes}} when is_list(Attributes) ->",nl,	  "               case lists:keysearch(asn1_info,1,Attributes) of",nl,	  "                  {value,{_,Info}} when is_list(Info) ->",nl,	  "                     Info;",nl,	  "                  _ ->",nl,	  "                     []",nl,	  "               end;",nl,	  "            _ ->",nl,	  "               []",nl,	  "         end",nl,	  "   end.",nl]).open_hrl(OutFile,Module) ->    File = lists:concat([OutFile,".hrl"]),    Fid = fopen(File,write),    put(gen_file_out,Fid),    gen_hrlhead(Module).%% EMIT functions ************************%% ***************************************						% debug generationdemit(Term) ->    case get(asndebug) of	true -> emit(Term);	_ ->true    end.						% always generationemit({external,_M,T}) ->    emit(T);emit({prev,Variable}) when atom(Variable) ->    emit({var,asn1ct_name:prev(Variable)});emit({next,Variable}) when atom(Variable) ->    emit({var,asn1ct_name:next(Variable)});emit({curr,Variable}) when atom(Variable) ->    emit({var,asn1ct_name:curr(Variable)});    emit({var,Variable}) when atom(Variable) ->    [Head|V] = atom_to_list(Variable),    emit([Head-32|V]);emit({var,Variable}) ->    [Head|V] = Variable,    emit([Head-32|V]);emit({asis,What}) ->    format(get(gen_file_out),"~w",[What]);emit(nl) ->    nl(get(gen_file_out));emit(com) ->    emit(",");emit(tab) ->    put_chars(get(gen_file_out),"     ");emit(What) when integer(What) ->    put_chars(get(gen_file_out),integer_to_list(What));emit(What) when list(What), integer(hd(What)) ->    put_chars(get(gen_file_out),What);emit(What) when atom(What) ->    put_chars(get(gen_file_out),atom_to_list(What));emit(What) when tuple(What) ->    emit_parts(tuple_to_list(What));emit(What) when list(What) ->    emit_parts(What);emit(X) ->    exit({'cant emit ',X}).emit_parts([]) -> true;emit_parts([H|T]) ->    emit(H),    emit_parts(T).format(undefined,X,Y) ->    io:format(X,Y);format(X,Y,Z) ->    io:format(X,Y,Z).nl(undefined) -> io:nl();nl(X) -> io:nl(X).put_chars(undefined,X) ->    io:put_chars(X);put_chars(Y,X) ->    io:put_chars(Y,X).fopen(F, Mode) ->    case file:open(F, Mode) of	{ok, Fd} -> 	    Fd;	{error, Reason} ->	    io:format("** Can't open file ~p ~n", [F]),	    exit({error,Reason})    end.pgen_hrl(Erules,Module,TypeOrVal,_Indent) ->    put(currmod,Module),    {Types,Values,Ptypes,_,_,_} = TypeOrVal,    Ret =	case pgen_hrltypes(Erules,Module,Ptypes++Types,0) of	    0 -> 		case Values of		    [] ->			0;		    _ ->			open_hrl(get(outfile),get(currmod)),			pgen_macros(Erules,Module,Values),			1		end;	    X ->		pgen_macros(Erules,Module,Values),		X	end,    case Ret of	0 ->	    0;	Y ->	    Fid = get(gen_file_out),	    file:close(Fid),	    io:format("--~p--~n",		      [{generated,lists:concat([get(outfile),".hrl"])}]),	    Y    end.pgen_macros(_,_,[]) ->    true;pgen_macros(Erules,Module,[H|T]) ->    Valuedef = asn1_db:dbget(Module,H),    gen_macro(Valuedef),    pgen_macros(Erules,Module,T).pgen_hrltypes(_,_,[],NumRecords) ->    NumRecords;pgen_hrltypes(Erules,Module,[H|T],NumRecords) ->%    io:format("records = ~p~n",NumRecords),    Typedef = asn1_db:dbget(Module,H),    AddNumRecords = gen_record(Typedef,NumRecords),    pgen_hrltypes(Erules,Module,T,NumRecords+AddNumRecords).%% Generates a macro for value Value defined in the ASN.1 modulegen_macro(Value) when record(Value,valuedef) ->    emit({"-define('",Value#valuedef.name,"', ",	  {asis,Value#valuedef.value},").",nl}).%% Generate record functions **************%% Generates an Erlang record for each named and unnamed SEQUENCE and SET in the ASN.1 %% module. If no SEQUENCE or SET is found there is no .hrl file generatedgen_record(Tdef,NumRecords) when record(Tdef,typedef) ->    Name = [Tdef#typedef.name],    Type = Tdef#typedef.typespec,    gen_record(type,Name,Type,NumRecords);gen_record(Tdef,NumRecords) when record(Tdef,ptypedef) ->    Name = [Tdef#ptypedef.name],    Type = Tdef#ptypedef.typespec,    gen_record(ptype,Name,Type,NumRecords).    gen_record(TorPtype,Name,[#'ComponentType'{name=Cname,typespec=Type}|T],Num) ->    Num2 = gen_record(TorPtype,[Cname|Name],Type,Num),    gen_record(TorPtype,Name,T,Num2);gen_record(TorPtype,Name,{Clist1,Clist2},Num) when list(Clist1), list(Clist2) ->    gen_record(TorPtype,Name,Clist1++Clist2,Num);gen_record(TorPtype,Name,[_|T],Num) -> % skip EXTENSIONMARK    gen_record(TorPtype,Name,T,Num);gen_record(_TorPtype,_Name,[],Num) ->    Num;gen_record(TorPtype,Name,Type,Num) when record(Type,type) ->        Def = Type#type.def,    Rec = case Def of	      Seq when record(Seq,'SEQUENCE') ->		  case Seq#'SEQUENCE'.pname of		      false ->			  {record,Seq#'SEQUENCE'.components};		      _Pname when TorPtype == type ->			  false;		      _ ->			  {record,Seq#'SEQUENCE'.components}		  end;	      Set when record(Set,'SET') ->		  case Set#'SET'.pname of		      false ->			  {record,Set#'SET'.components};		      _Pname when TorPtype == type ->			  false;		      _ ->			  {record,Set#'SET'.components}		  end;%	      {'SET',{_,_CompList}} -> %		  {record,_CompList}; 	      {'CHOICE',_CompList} -> {inner,Def};	      {'SEQUENCE OF',_CompList} -> {['SEQOF'|Name],Def};	      {'SET OF',_CompList} -> {['SETOF'|Name],Def};	      _ -> false    end,    case Rec of	false -> Num;	{record,CompList} ->	    case Num of		0 -> open_hrl(get(outfile),get(currmod));		_ -> true	    end,	    emit({"-record('",list2name(Name),"',{",nl}),	    RootList = case CompList of			   _ when list(CompList) ->			       CompList;			   {_Rl,_} -> _Rl		       end,	    gen_record2(Name,'SEQUENCE',RootList),	    NewCompList = 		case CompList of		    {CompList1,[]} ->			emit({"}). % with extension mark",nl,nl}),			CompList1;		    {Tr,ExtensionList2} ->			case Tr of			    [] -> true;			    _ -> emit({",",nl})			end,			emit({"%% with extensions",nl}),			gen_record2(Name, 'SEQUENCE', ExtensionList2,				    "", ext),			emit({"}).",nl,nl}),			Tr ++ ExtensionList2;		    _ -> 			emit({"}).",nl,nl}),			CompList		end,	    gen_record(TorPtype,Name,NewCompList,Num+1);	{inner,{'CHOICE', CompList}} ->	    gen_record(TorPtype,Name,CompList,Num);	{NewName,{_, CompList}} ->	    gen_record(TorPtype,NewName,CompList,Num)    end;gen_record(_,_,_,NumRecords) -> % skip CLASS etc for now.     NumRecords.		    gen_head(Erules,Mod,Hrl) ->    Options = get(encoding_options),    {Rtmac,Rtmod} = case Erules of			per ->			    emit({"%% Generated by the Erlang ASN.1 PER-"				  "compiler version:",asn1ct:vsn(),nl}),			    {"RT_PER",?RT_PER_BIN};			ber ->			    emit({"%% Generated by the Erlang ASN.1 BER-"				  "compiler version:",asn1ct:vsn(),nl}),			    {"RT_BER",?RT_BER_BIN};			per_bin ->			    emit({"%% Generated by the Erlang ASN.1 BER-"				  "compiler version, utilizing bit-syntax:",				  asn1ct:vsn(),nl}),			    %% temporary code to enable rt2ct optimization			    case lists:member(optimize,Options) of				true -> {"RT_PER","asn1rt_per_bin_rt2ct"};				_ ->				    {"RT_PER",?RT_PER_BIN}			    end;			ber_bin ->			    emit({"%% Generated by the Erlang ASN.1 BER-"				  "compiler version, utilizing bit-syntax:",				  asn1ct:vsn(),nl}),			    {"RT_BER",?RT_BER_BIN};			ber_bin_v2 ->			    emit({"%% Generated by the Erlang ASN.1 BER_V2-"				  "compiler version, utilizing bit-syntax:",				  asn1ct:vsn(),nl}),			    {"RT_BER","asn1rt_ber_bin_v2"}    end,    emit({"%% Purpose: encoder and decoder to the types in mod ",Mod,nl,nl}),    emit({"-module('",Mod,"').",nl}),    put(currmod,Mod),    %emit({"-compile(export_all).",nl}),    case Hrl of	0 -> true;	_ -> 	    emit({"-include(\"",Mod,".hrl\").",nl})    end,    emit(["-define('",Rtmac,"',",Rtmod,").",nl]),    emit(["-asn1_info([{vsn,'",asn1ct:vsn(),"'},",nl,	  "            {module,'",Mod,"'},",nl,	  "            {options,",io_lib:format("~w",[Options]),"}]).",nl,nl]).			gen_hrlhead(Mod) ->    emit({"%% Generated by the Erlang ASN.1 compiler version:",asn1ct:vsn(),nl}),    emit({"%% Purpose: Erlang record definitions for each named and unnamed",nl}),    emit({"%% SEQUENCE and SET, and macro definitions for each value",nl}),    emit({"%% definition,in module ",Mod,nl,nl}),    emit({nl,nl}).gen_record2(Name,SeqOrSet,Comps) ->    gen_record2(Name,SeqOrSet,Comps,"",noext).gen_record2(_Name,_SeqOrSet,[],_Com,_Extension) ->    true;gen_record2(Name,SeqOrSet,[{'EXTENSIONMARK',_,_}|T],Com,Extension) ->    gen_record2(Name,SeqOrSet,T,Com,Extension);gen_record2(_Name,_SeqOrSet,[H],Com,Extension) ->    #'ComponentType'{name=Cname} = H,    emit(Com),    emit({asis,Cname}),    gen_record_default(H, Extension);gen_record2(Name,SeqOrSet,[H|T],Com, Extension) ->    #'ComponentType'{name=Cname} = H,    emit(Com),    emit({asis,Cname}),    gen_record_default(H, Extension),%    emit(", "),    gen_record2(Name,SeqOrSet,T,", ", Extension).%gen_record_default(C, ext) ->%    emit(" = asn1_NOEXTVALUE");gen_record_default(#'ComponentType'{prop='OPTIONAL'}, _)->    emit(" = asn1_NOVALUE"); gen_record_default(#'ComponentType'{prop={'DEFAULT',_}}, _)->    emit(" = asn1_DEFAULT"); gen_record_default(_, _) ->    true.gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->    case WhatKind of	{primitive,bif} ->	    gen_prim_check_call(InnerType,DefaultValue,Element,Type);	#'Externaltypereference'{module=M,type=T} ->	    %% generate function call

⌨️ 快捷键说明

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