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 + -
显示快捷键?