aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src/asn1ct_gen.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1/src/asn1ct_gen.erl')
-rw-r--r--lib/asn1/src/asn1ct_gen.erl668
1 files changed, 284 insertions, 384 deletions
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index bfaffa13bf..9943bd056a 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -34,10 +34,10 @@
insert_once/2,
ct_gen_module/1,
index2suffix/1,
- get_record_name_prefix/0,
+ get_record_name_prefix/1,
conform_value/2,
named_bitstring_value/2]).
--export([pgen/5,
+-export([pgen/3,
mk_var/1,
un_hyphen_var/1]).
-export([gen_encode_constructed/4,
@@ -45,23 +45,19 @@
-define(SUPPRESSION_FUNC, 'dialyzer-suppressions').
+
%% pgen(Outfile, Erules, Module, TypeOrVal, Options)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList}
-%% TypeList = ValueList = [atom()]
-%% Options = [Options] from asn1ct:compile()
-
-pgen(OutFile,Erules,Module,TypeOrVal,Options) ->
- pgen_module(OutFile,Erules,Module,TypeOrVal,Options,true).
-
-
-pgen_module(OutFile,Erules,Module,
- TypeOrVal = {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets},
- Options,Indent) ->
- N2nConvEnums = [CName|| {n2n,CName} <- get(encoding_options)],
+%% Generate Erlang module (.erl) and (.hrl) file corresponding to
+%% an ASN.1 module. The .hrl file is only generated if necessary.
+
+-spec pgen(Outfile, Gen, Code) -> 'ok' when
+ Outfile :: any(),
+ Gen :: #gen{},
+ Code :: #abst{}.
+
+pgen(OutFile, #gen{options=Options}=Gen, Code) ->
+ #abst{name=Module,types=Types} = Code,
+ N2nConvEnums = [CName|| {n2n,CName} <- Options],
case N2nConvEnums -- Types of
[] ->
ok;
@@ -69,30 +65,30 @@ pgen_module(OutFile,Erules,Module,
exit({"Non existing ENUMERATION types used in n2n option",
UnmatchedTypes})
end,
- put(outfile,OutFile),
- HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent),
+ put(outfile, OutFile),
+ put(currmod, Module),
+ HrlGenerated = pgen_hrl(Gen, Code),
asn1ct_name:start(),
ErlFile = lists:concat([OutFile,".erl"]),
_ = open_output_file(ErlFile),
asn1ct_func:start_link(),
- gen_head(Erules,Module,HrlGenerated),
- pgen_exports(Erules,Module,TypeOrVal),
- pgen_dispatcher(Erules,Module,TypeOrVal),
+ gen_head(Gen, Module, HrlGenerated),
+ pgen_exports(Gen, Code),
+ pgen_dispatcher(Gen, Types),
pgen_info(),
- pgen_typeorval(Erules,Module,N2nConvEnums,TypeOrVal),
- pgen_partial_incomplete_decode(Erules),
-% gen_vars(asn1_db:mod_to_vars(Module)),
-% gen_tag_table(AllTypes),
+ pgen_typeorval(Gen, N2nConvEnums, Code),
+ pgen_partial_incomplete_decode(Gen),
emit([nl,
"%%%",nl,
"%%% Run-time functions.",nl,
"%%%",nl]),
- dialyzer_suppressions(Erules),
+ dialyzer_suppressions(Gen),
Fd = get(gen_file_out),
asn1ct_func:generate(Fd),
close_output_file(),
_ = erase(outfile),
- asn1ct:verbose("--~p--~n",[{generated,ErlFile}],Options).
+ asn1ct:verbose("--~p--~n", [{generated,ErlFile}], Gen),
+ ok.
dialyzer_suppressions(Erules) ->
emit([nl,
@@ -100,20 +96,27 @@ dialyzer_suppressions(Erules) ->
Rtmod = ct_gen_module(Erules),
Rtmod:dialyzer_suppressions(Erules).
-pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) ->
+pgen_typeorval(Erules, N2nConvEnums, Code) ->
+ #abst{name=Module,types=Types,values=Values,
+ objects=Objects,objsets=ObjectSets} = Code,
Rtmod = ct_gen_module(Erules),
pgen_types(Rtmod,Erules,N2nConvEnums,Module,Types),
- pgen_values(Erules,Module,Values),
+ pgen_values(Values, Module),
pgen_objects(Rtmod,Erules,Module,Objects),
pgen_objectsets(Rtmod,Erules,Module,ObjectSets),
pgen_partial_decode(Rtmod,Erules,Module).
-pgen_values(_,_,[]) ->
- true;
-pgen_values(Erules,Module,[H|T]) ->
- Valuedef = asn1_db:dbget(Module,H),
- gen_value(Valuedef),
- pgen_values(Erules,Module,T).
+%% Generate a function 'V'/0 for each Value V defined in the ASN.1 module.
+%% The function returns the value in an Erlang representation which can be
+%% used as input to the runtime encode functions.
+
+pgen_values([H|T], Module) ->
+ #valuedef{name=Name,value=Value} = asn1_db:dbget(Module, H),
+ emit([{asis,Name},"() ->",nl,
+ {asis,Value},".",nl,nl]),
+ pgen_values(T, Module);
+pgen_values([], _) ->
+ ok.
pgen_types(_, _, _, _, []) ->
true;
@@ -181,10 +184,10 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) ->
Rtmod:gen_objectset_code(Erules,TypeDef),
pgen_objectsets(Rtmod,Erules,Module,T).
-pgen_partial_decode(Rtmod,Erule,Module) when Erule == ber ->
- pgen_partial_inc_dec(Rtmod,Erule,Module),
- pgen_partial_dec(Rtmod,Erule,Module);
-pgen_partial_decode(_,_,_) ->
+pgen_partial_decode(Rtmod, #gen{erule=ber}=Gen, Module) ->
+ pgen_partial_inc_dec(Rtmod, Gen, Module),
+ pgen_partial_dec(Rtmod, Gen, Module);
+pgen_partial_decode(_, _, _) ->
ok.
pgen_partial_inc_dec(Rtmod,Erules,Module) ->
@@ -225,7 +228,7 @@ pgen_partial_inc_dec1(Rtmod,Erules,Module,[P|Ps]) ->
pgen_partial_inc_dec1(_,_,_,[]) ->
ok.
-gen_partial_inc_dec_refed_funcs(Rtmod,Erule) when Erule == ber ->
+gen_partial_inc_dec_refed_funcs(Rtmod, #gen{erule=ber}=Gen) ->
case asn1ct:next_refed_func() of
[] ->
ok;
@@ -233,19 +236,17 @@ gen_partial_inc_dec_refed_funcs(Rtmod,Erule) when Erule == ber ->
TypeDef = asn1_db:dbget(M,Name),
asn1ct:update_gen_state(namelist,Pattern),
asn1ct:set_current_sindex(Sindex),
- Rtmod:gen_inc_decode(Erule,TypeDef),
- gen_dec_part_inner_constr(Rtmod,Erule,TypeDef,[Name]),
- gen_partial_inc_dec_refed_funcs(Rtmod,Erule);
+ Rtmod:gen_inc_decode(Gen, TypeDef),
+ gen_dec_part_inner_constr(Rtmod, Gen, TypeDef, [Name]),
+ gen_partial_inc_dec_refed_funcs(Rtmod, Gen);
{Name,Sindex,Pattern,Type} ->
TypeDef=#typedef{name=asn1ct_gen:list2name(Name),typespec=Type},
asn1ct:update_gen_state(namelist,Pattern),
asn1ct:set_current_sindex(Sindex),
- Rtmod:gen_inc_decode(Erule,TypeDef),
- gen_dec_part_inner_constr(Rtmod,Erule,TypeDef,Name),
- gen_partial_inc_dec_refed_funcs(Rtmod,Erule)
- end;
-gen_partial_inc_dec_refed_funcs(_,_) ->
- ok.
+ Rtmod:gen_inc_decode(Gen, TypeDef),
+ gen_dec_part_inner_constr(Rtmod, Gen, TypeDef, Name),
+ gen_partial_inc_dec_refed_funcs(Rtmod, Gen)
+ end.
pgen_partial_dec(_Rtmod,Erules,_Module) ->
Type_pattern = asn1ct:get_gen_state_field(type_pattern),
@@ -254,16 +255,16 @@ pgen_partial_dec(_Rtmod,Erules,_Module) ->
pgen_partial_types(Erules,Type_pattern),
ok.
-pgen_partial_types(Erules,Type_pattern) ->
- % until this functionality works on all back-ends
- Options = get(encoding_options),
- case lists:member(asn1config,Options) of
+pgen_partial_types(#gen{options=Options}=Gen, TypePattern) ->
+ %% until this functionality works on all back-ends
+ case lists:member(asn1config, Options) of
true ->
- pgen_partial_types1(Erules,Type_pattern);
- _ -> ok
+ pgen_partial_types1(Gen, TypePattern);
+ false ->
+ ok
end.
-
+
pgen_partial_types1(Erules,[{FuncName,[TopType|RestTypes]}|Rest]) ->
% emit([FuncName,"(Bytes) ->",nl]),
CurrMod = get(currmod),
@@ -441,7 +442,8 @@ pgen_partial_incomplete_decode(Erule) ->
_ ->
ok
end.
-pgen_partial_incomplete_decode1(ber) ->
+
+pgen_partial_incomplete_decode1(#gen{erule=ber}) ->
case asn1ct:read_config_data(partial_incomplete_decode) of
undefined ->
ok;
@@ -451,7 +453,7 @@ pgen_partial_incomplete_decode1(ber) ->
GeneratedFs= asn1ct:get_gen_state_field(gen_refed_funcs),
% io:format("GeneratedFs :~n~p~n",[GeneratedFs]),
gen_part_decode_funcs(GeneratedFs,0);
-pgen_partial_incomplete_decode1(_) -> ok.
+pgen_partial_incomplete_decode1(#gen{}) -> ok.
emit_partial_incomplete_decode({FuncName,TopType,Pattern}) ->
TypePattern = asn1ct:get_gen_state_field(inc_type_pattern),
@@ -578,18 +580,6 @@ un_hyphen_var([H|T]) ->
un_hyphen_var([]) ->
[].
-%% Generate value functions ***************
-%% ****************************************
-%% Generates a function 'V'/0 for each Value V defined in the ASN.1 module
-%% the function returns the value in an Erlang representation which can be
-%% used as input to the runtime encode functions
-
-gen_value(Value) when is_record(Value,valuedef) ->
-%% io:format(" ~w ",[Value#valuedef.name]),
- emit({"'",Value#valuedef.name,"'() ->",nl}),
- V = Value#valuedef.value,
- emit([{asis,V},".",nl,nl]).
-
gen_encode_constructed(Erules,Typename,InnerType,D) when is_record(D,type) ->
Rtmod = ct_constructed_module(Erules),
case InnerType of
@@ -654,78 +644,32 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) ->
gen_decode_constructed(Erules,Typename,InnerType,D#typedef.typespec).
-pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
- emit(["-export([encoding_rule/0,bit_string_format/0,",nl,
+pgen_exports(#gen{options=Options}=Gen, Code) ->
+ #abst{types=Types,values=Values,objects=Objects,objsets=ObjectSets} = Code,
+ emit(["-export([encoding_rule/0,maps/0,bit_string_format/0,",nl,
" legacy_erlang_types/0]).",nl]),
emit(["-export([",{asis,?SUPPRESSION_FUNC},"/1]).",nl]),
- case Types of
- [] -> ok;
- _ ->
- emit({"-export([",nl}),
- case Erules of
- ber ->
- gen_exports1(Types,"enc_",2);
- _ ->
- gen_exports1(Types,"enc_",1)
- end,
- emit({"-export([",nl}),
- case Erules of
- ber ->
- gen_exports1(Types, "dec_", 2);
- _ ->
- gen_exports1(Types, "dec_", 1)
- end
- end,
- case [X || {n2n,X} <- get(encoding_options)] of
- [] -> ok;
- A2nNames ->
- emit({"-export([",nl}),
- gen_exports1(A2nNames,"name2num_",1),
- emit({"-export([",nl}),
- gen_exports1(A2nNames,"num2name_",1)
- end,
- case Values of
- [] -> ok;
- _ ->
- emit({"-export([",nl}),
- gen_exports1(Values,"",0)
+ case Gen of
+ #gen{erule=ber} ->
+ gen_exports(Types, "enc_", 2),
+ gen_exports(Types, "dec_", 2),
+ gen_exports(Objects, "enc_", 3),
+ gen_exports(Objects, "dec_", 3),
+ gen_exports(ObjectSets, "getenc_", 1),
+ gen_exports(ObjectSets, "getdec_", 1);
+ #gen{erule=per} ->
+ gen_exports(Types, "enc_", 1),
+ gen_exports(Types, "dec_", 1)
end,
- case Objects of
- [] -> ok;
- _ ->
- case erule(Erules) of
- per ->
- ok;
- ber ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",3),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",3)
- end
- end,
- case ObjectSets of
- [] -> ok;
- _ ->
- case erule(Erules) of
- per ->
- ok;
- ber ->
- emit({"-export([",nl}),
- gen_exports1(ObjectSets, "getenc_",1),
- emit({"-export([",nl}),
- gen_exports1(ObjectSets, "getdec_",1)
- end
- end,
- emit({"-export([info/0]).",nl}),
- gen_partial_inc_decode_exports(),
- gen_selected_decode_exports(),
- emit({nl,nl}).
-gen_exports1([F1,F2|T],Prefix,Arity) ->
- emit({"'",Prefix,F1,"'/",Arity,com,nl}),
- gen_exports1([F2|T],Prefix,Arity);
-gen_exports1([Flast|_T],Prefix,Arity) ->
- emit({"'",Prefix,Flast,"'/",Arity,nl,"]).",nl,nl}).
+ A2nNames = [X || {n2n,X} <- Options],
+ gen_exports(A2nNames, "name2num_", 1),
+ gen_exports(A2nNames, "num2name_", 1),
+
+ gen_exports(Values, "", 0),
+ emit(["-export([info/0]).",nl,nl]),
+ gen_partial_inc_decode_exports(),
+ gen_selected_decode_exports().
gen_partial_inc_decode_exports() ->
case {asn1ct:read_config_data(partial_incomplete_decode),
@@ -734,66 +678,54 @@ gen_partial_inc_decode_exports() ->
ok;
{_,undefined} ->
ok;
- {Data,_} ->
- gen_partial_inc_decode_exports(Data),
- emit(["-export([decode_part/2]).",nl])
+ {Data0,_} ->
+ Data = [Name || {Name,_,_} <- Data0],
+ gen_exports(Data, "", 1),
+ emit(["-export([decode_part/2]).",nl,nl])
end.
-gen_partial_inc_decode_exports([]) ->
- ok;
-gen_partial_inc_decode_exports([{Name,_,_}|Rest]) ->
- emit(["-export([",Name,"/1"]),
- gen_partial_inc_decode_exports1(Rest);
-gen_partial_inc_decode_exports([_|Rest]) ->
- gen_partial_inc_decode_exports(Rest).
-
-gen_partial_inc_decode_exports1([]) ->
- emit(["]).",nl]);
-gen_partial_inc_decode_exports1([{Name,_,_}|Rest]) ->
- emit([", ",Name,"/1"]),
- gen_partial_inc_decode_exports1(Rest);
-gen_partial_inc_decode_exports1([_|Rest]) ->
- gen_partial_inc_decode_exports1(Rest).
gen_selected_decode_exports() ->
case asn1ct:get_gen_state_field(type_pattern) of
undefined ->
ok;
- L ->
- gen_selected_decode_exports(L)
+ Data0 ->
+ Data = [Name || {Name,_} <- Data0],
+ gen_exports(Data, "", 1)
end.
-gen_selected_decode_exports([]) ->
+gen_exports([], _Prefix, _Arity) ->
ok;
-gen_selected_decode_exports([{FuncName,_}|Rest]) ->
- emit(["-export([",FuncName,"/1"]),
- gen_selected_decode_exports1(Rest).
-gen_selected_decode_exports1([]) ->
- emit(["]).",nl,nl]);
-gen_selected_decode_exports1([{FuncName,_}|Rest]) ->
- emit([",",nl," ",FuncName,"/1"]),
- gen_selected_decode_exports1(Rest).
-
-pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) ->
+gen_exports([_|_]=L0, Prefix, Arity) ->
+ FF = fun(F0) ->
+ F = list_to_atom(lists:concat([Prefix,F0])),
+ [{asis,F},"/",Arity]
+ end,
+ L = lists:join(",\n", [FF(F) || F <- L0]),
+ emit(["-export([",nl,
+ L,nl,
+ "]).",nl,nl]).
+
+pgen_dispatcher(Erules, []) ->
gen_info_functions(Erules);
-pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
+pgen_dispatcher(Gen, Types) ->
emit(["-export([encode/2,decode/2]).",nl,nl]),
- gen_info_functions(Erules),
+ gen_info_functions(Gen),
- Options = get(encoding_options),
+ Options = Gen#gen.options,
NoFinalPadding = lists:member(no_final_padding, Options),
NoOkWrapper = proplists:get_bool(no_ok_wrapper, Options),
- Call = case Erules of
- per ->
- asn1ct_func:need({Erules,complete,1}),
+ Call = case Gen of
+ #gen{erule=per,aligned=true} ->
+ asn1ct_func:need({per,complete,1}),
"complete(encode_disp(Type, Data))";
- ber ->
+ #gen{erule=ber} ->
"iolist_to_binary(element(1, encode_disp(Type, Data)))";
- uper when NoFinalPadding == true ->
- asn1ct_func:need({Erules,complete_NFP,1}),
+ #gen{erule=per,aligned=false} when NoFinalPadding ->
+ asn1ct_func:need({uper,complete_NFP,1}),
"complete_NFP(encode_disp(Type, Data))";
- uper ->
- asn1ct_func:need({Erules,complete,1}),
+ #gen{erule=per,aligned=false} ->
+ asn1ct_func:need({uper,complete,1}),
"complete(encode_disp(Type, Data))"
end,
@@ -809,36 +741,36 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
end,
emit([nl,nl]),
- Return_rest = proplists:get_bool(undec_rest, Options),
- Data = case {Erules,Return_rest} of
- {ber,true} -> "Data0";
- _ -> "Data"
+ ReturnRest = proplists:get_bool(undec_rest, Gen#gen.options),
+ Data = case Gen#gen.erule =:= ber andalso ReturnRest of
+ true -> "Data0";
+ false -> "Data"
end,
- emit(["decode(Type,",Data,") ->",nl]),
+ emit(["decode(Type, ",Data,") ->",nl]),
DecWrap =
- case {Erules,Return_rest} of
- {ber,false} ->
+ case {Gen,ReturnRest} of
+ {#gen{erule=ber},false} ->
asn1ct_func:need({ber,ber_decode_nif,1}),
"element(1, ber_decode_nif(Data))";
- {ber,true} ->
+ {#gen{erule=ber},true} ->
asn1ct_func:need({ber,ber_decode_nif,1}),
emit(["{Data,Rest} = ber_decode_nif(Data0),",nl]),
"Data";
- _ ->
+ {_,_} ->
"Data"
end,
emit([case NoOkWrapper of
false -> "try";
true -> "case"
end, " decode_disp(Type, ",DecWrap,") of",nl]),
- case erule(Erules) of
- ber ->
+ case Gen of
+ #gen{erule=ber} ->
emit([" Result ->",nl]);
- per ->
+ #gen{erule=per} ->
emit([" {Result,Rest} ->",nl])
end,
- case Return_rest of
+ case ReturnRest of
false -> result_line(NoOkWrapper, ["Result"]);
true -> result_line(NoOkWrapper, ["Result","Rest"])
end,
@@ -849,18 +781,11 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
emit([nl,"end.",nl,nl])
end,
- gen_decode_partial_incomplete(Erules),
+ gen_decode_partial_incomplete(Gen),
+ gen_partial_inc_dispatcher(Gen),
- case Erules of
- ber ->
- 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_","")
- end,
- emit([nl,nl]).
+ gen_dispatcher(Types, "encode_disp", "enc_"),
+ gen_dispatcher(Types, "decode_disp", "dec_").
result_line(NoOkWrapper, Items) ->
S = [" "|case NoOkWrapper of
@@ -885,15 +810,26 @@ try_catch() ->
" end",nl,
"end."].
-gen_info_functions(Erules) ->
+gen_info_functions(Gen) ->
+ Erule = case Gen of
+ #gen{erule=ber} -> ber;
+ #gen{erule=per,aligned=false} -> uper;
+ #gen{erule=per,aligned=true} -> per
+ end,
+ Maps = case Gen of
+ #gen{pack=record} -> false;
+ #gen{pack=map} -> true
+ end,
emit(["encoding_rule() -> ",
- {asis,Erules},".",nl,nl,
+ {asis,Erule},".",nl,nl,
+ "maps() -> ",
+ {asis,Maps},".",nl,nl,
"bit_string_format() -> ",
{asis,asn1ct:get_bit_string_format()},".",nl,nl,
"legacy_erlang_types() -> ",
{asis,asn1ct:use_legacy_types()},".",nl,nl]).
-gen_decode_partial_incomplete(ber) ->
+gen_decode_partial_incomplete(#gen{erule=ber}) ->
case {asn1ct:read_config_data(partial_incomplete_decode),
asn1ct:get_gen_state_field(inc_type_pattern)} of
{undefined,_} ->
@@ -931,10 +867,10 @@ gen_decode_partial_incomplete(ber) ->
EmitCaseClauses(),
emit([".",nl,nl])
end;
-gen_decode_partial_incomplete(_Erule) ->
+gen_decode_partial_incomplete(#gen{}) ->
ok.
-gen_partial_inc_dispatcher() ->
+gen_partial_inc_dispatcher(#gen{erule=ber}) ->
case {asn1ct:read_config_data(partial_incomplete_decode),
asn1ct:get_gen_state_field(inc_type_pattern)} of
{undefined,_} ->
@@ -944,7 +880,9 @@ gen_partial_inc_dispatcher() ->
{Data1,Data2} ->
% io:format("partial_incomplete_decode: ~p~ninc_type_pattern: ~p~n",[Data,Data2]),
gen_partial_inc_dispatcher(Data1, Data2, "")
- end.
+ end;
+gen_partial_inc_dispatcher(#gen{}) ->
+ ok.
gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest], TypePattern, Sep) ->
TPattern =
@@ -968,12 +906,18 @@ gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest], TypePattern, Sep)
gen_partial_inc_dispatcher([], _, _) ->
emit([".",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]).
+gen_dispatcher(L, DispFunc, Prefix) ->
+ gen_dispatcher_1(L, DispFunc, Prefix),
+ emit([DispFunc,"(","Type",", _Data) ->"
+ " exit({error,{asn1,{undefined_type,Type}}}).",nl,nl]).
+
+gen_dispatcher_1([F|T], FuncName, Prefix) ->
+ Func = list_to_atom(lists:concat([Prefix,F])),
+ emit([FuncName,"(",{asis,F},", Data) -> ",
+ {asis,Func},"(Data)",";",nl]),
+ gen_dispatcher_1(T, FuncName, Prefix);
+gen_dispatcher_1([], _, _) ->
+ ok.
pgen_info() ->
emit(["info() ->",nl,
@@ -1092,22 +1036,21 @@ open_output_file(F) ->
close_output_file() ->
ok = file:close(erase(gen_file_out)).
-pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) ->
- put(currmod,Module),
- {Types,Values,Ptypes,_,_,_} = TypeOrVal,
+pgen_hrl(#gen{pack=record}=Gen, Code) ->
+ #abst{name=Module,types=Types,values=Values,ptypes=Ptypes} = Code,
Ret =
- case pgen_hrltypes(Erules,Module,Ptypes++Types,0) of
+ case pgen_hrltypes(Gen, Module, Ptypes++Types, 0) of
0 ->
case Values of
[] ->
0;
_ ->
- open_hrl(get(outfile),get(currmod)),
- pgen_macros(Erules,Module,Values),
+ open_hrl(get(outfile), Module),
+ pgen_macros(Gen, Module, Values),
1
end;
X ->
- pgen_macros(Erules,Module,Values),
+ pgen_macros(Gen, Module, Values),
X
end,
case Ret of
@@ -1119,62 +1062,61 @@ pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) ->
close_output_file(),
asn1ct:verbose("--~p--~n",
[{generated,lists:concat([get(outfile),".hrl"])}],
- Options),
+ Gen),
Y
- end.
+ end;
+pgen_hrl(#gen{pack=map}, _) ->
+ 0.
pgen_macros(_,_,[]) ->
true;
-pgen_macros(Erules,Module,[H|T]) ->
- Valuedef = asn1_db:dbget(Module,H),
- gen_macro(Valuedef),
- pgen_macros(Erules,Module,T).
+pgen_macros(Gen, Module, [H|T]) ->
+ Valuedef = asn1_db:dbget(Module, H),
+ gen_macro(Gen, Valuedef),
+ pgen_macros(Gen, 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).
+pgen_hrltypes(Gen, Module, [H|T], NumRecords) ->
+ Typedef = asn1_db:dbget(Module, H),
+ AddNumRecords = gen_record(Gen, Typedef, NumRecords),
+ pgen_hrltypes(Gen, Module, T, NumRecords+AddNumRecords).
%% Generates a macro for value Value defined in the ASN.1 module
-gen_macro(Value) when is_record(Value,valuedef) ->
- Prefix = get_macro_name_prefix(),
- emit({"-define('",Prefix,Value#valuedef.name,"', ",
- {asis,Value#valuedef.value},").",nl}).
+gen_macro(Gen, #valuedef{name=Name,value=Value}) ->
+ Prefix = get_macro_name_prefix(Gen),
+ emit(["-define('",Prefix,Name,"', ",{asis,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 generated
-gen_record(Tdef,NumRecords) when is_record(Tdef,typedef) ->
+gen_record(Gen, #typedef{}=Tdef, NumRecords) ->
Name = [Tdef#typedef.name],
Type = Tdef#typedef.typespec,
- gen_record(type,Name,Type,NumRecords);
-
-gen_record(Tdef,NumRecords) when is_record(Tdef,ptypedef) ->
+ gen_record(Gen, type, Name, Type, NumRecords);
+gen_record(Gen, #ptypedef{}=Tdef, NumRecords) ->
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)
+ gen_record(Gen, ptype, Name, Type, NumRecords).
+
+gen_record(Gen, TorPtype, Name,
+ [#'ComponentType'{name=Cname,typespec=Type}|T], Num) ->
+ Num2 = gen_record(Gen, TorPtype, [Cname|Name], Type, Num),
+ gen_record(Gen, TorPtype, Name, T, Num2);
+gen_record(Gen, TorPtype, Name, {Clist1,Clist2}, Num)
when is_list(Clist1), is_list(Clist2) ->
- gen_record(TorPtype,Name,Clist1++Clist2,Num);
-gen_record(TorPtype,Name,{Clist1,EClist,Clist2},Num)
+ gen_record(Gen, TorPtype, Name, Clist1++Clist2, Num);
+gen_record(Gen, TorPtype, Name, {Clist1,EClist,Clist2}, Num)
when is_list(Clist1), is_list(EClist), is_list(Clist2) ->
- gen_record(TorPtype,Name,Clist1++EClist++Clist2,Num);
-gen_record(TorPtype,Name,[_|T],Num) -> % skip EXTENSIONMARK
- gen_record(TorPtype,Name,T,Num);
-gen_record(_TorPtype,_Name,[],Num) ->
+ gen_record(Gen, TorPtype, Name, Clist1++EClist++Clist2, Num);
+gen_record(Gen, TorPtype, Name, [_|T], Num) -> % skip EXTENSIONMARK
+ gen_record(Gen, TorPtype, Name, T, Num);
+gen_record(_Gen, _TorPtype, _Name, [], Num) ->
Num;
-
-gen_record(TorPtype,Name,Type,Num) when is_record(Type,type) ->
+gen_record(Gen, TorPtype, Name, #type{}=Type, Num) ->
Def = Type#type.def,
Rec = case Def of
Seq when is_record(Seq,'SEQUENCE') ->
@@ -1209,127 +1151,103 @@ gen_record(TorPtype,Name,Type,Num) when is_record(Type,type) ->
0 -> open_hrl(get(outfile),get(currmod));
_ -> true
end,
- Prefix = get_record_name_prefix(),
- emit({"-record('",Prefix,list2name(Name),"',{",nl}),
- RootList = case CompList of
- _ when is_list(CompList) ->
- CompList;
- {Rl,_} -> Rl;
- {Rl1,_Ext,_Rl2} -> Rl1
- end,
- gen_record2(Name,'SEQUENCE',RootList),
- NewCompList =
+ do_gen_record(Gen, Name, CompList),
+ 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;
{Rootl1,Extl,Rootl2} ->
- case Rootl1 =/= [] andalso Extl++Rootl2 =/= [] of
- true -> emit([com]);
- false -> ok
- end,
- case Rootl1 of
- [_|_] -> emit([nl]);
- [] -> ok
- end,
- emit(["%% with extensions",nl]),
- gen_record2(Name,'SEQUENCE',Extl,"",ext),
- case Extl =/= [] andalso Rootl2 =/= [] of
- true -> emit([com]);
- false -> ok
- end,
- case Extl of
- [_|_] -> emit([nl]);
- [] -> ok
- end,
- emit(["%% end of extensions",nl]),
- gen_record2(Name,'SEQUENCE',Rootl2,"",noext),
- emit(["}).",nl,nl]),
Rootl1++Extl++Rootl2;
- _ ->
- emit({"}).",nl,nl}),
+ _ ->
CompList
end,
- gen_record(TorPtype,Name,NewCompList,Num+1);
+ gen_record(Gen, TorPtype, Name, NewCompList, Num+1);
{inner,{'CHOICE', CompList}} ->
- gen_record(TorPtype,Name,CompList,Num);
+ gen_record(Gen, TorPtype, Name, CompList, Num);
{NewName,{_, CompList}} ->
- gen_record(TorPtype,NewName,CompList,Num)
+ gen_record(Gen, TorPtype, NewName, CompList, Num)
end;
-gen_record(_,_,_,NumRecords) -> % skip CLASS etc for now.
+gen_record(_, _, _, _, NumRecords) -> % skip CLASS etc for now.
NumRecords.
-
-gen_head(Erules,Mod,Hrl) ->
- Options = get(encoding_options),
- case Erules of
- per ->
- emit(["%% Generated by the Erlang ASN.1 PER-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl]);
- ber ->
- emit(["%% Generated by the Erlang ASN.1 BER_V2-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl]);
- uper ->
- emit(["%% Generated by the Erlang ASN.1 UNALIGNED"
- " PER-compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl])
+
+do_gen_record(Gen, Name, CL0) ->
+ CL = case CL0 of
+ {Root,[]} ->
+ Root ++ [{comment,"with extension mark"}];
+ {Root,Ext} ->
+ Root ++ [{comment,"with exensions"}] ++
+ only_components(Ext);
+ {Root1,Ext,Root2} ->
+ Root1 ++ [{comment,"with exensions"}] ++
+ only_components(Ext) ++
+ [{comment,"end of extensions"}] ++ Root2;
+ _ when is_list(CL0) ->
+ CL0
+ end,
+ Prefix = get_record_name_prefix(Gen),
+ emit(["-record('",Prefix,list2name(Name),"', {"] ++
+ do_gen_record_1(CL) ++
+ [nl,"}).",nl,nl]).
+
+only_components(CL) ->
+ [C || #'ComponentType'{}=C <- CL].
+
+do_gen_record_1([#'ComponentType'{name=Name,prop=Prop}|T]) ->
+ Val = case Prop of
+ 'OPTIONAL' ->
+ " = asn1_NOVALUE";
+ {'DEFAULT',_} ->
+ " = asn1_DEFAULT";
+ _ ->
+ []
+ end,
+ Com = case needs_trailing_comma(T) of
+ true -> [com];
+ false -> []
end,
- emit({"%% Purpose: encoder and decoder to the types in mod ",Mod,nl,nl}),
- emit({"-module('",Mod,"').",nl}),
- put(currmod,Mod),
- emit({"-compile(nowarn_unused_vars).",nl}),
- emit({"-dialyzer(no_improper_lists).",nl}),
+ [nl," ",{asis,Name},Val,Com|do_gen_record_1(T)];
+do_gen_record_1([{comment,Text}|T]) ->
+ [nl," %% ",Text|do_gen_record_1(T)];
+do_gen_record_1([]) ->
+ [].
+
+needs_trailing_comma([#'ComponentType'{}|_]) -> true;
+needs_trailing_comma([_|T]) -> needs_trailing_comma(T);
+needs_trailing_comma([]) -> false.
+
+gen_head(#gen{options=Options}=Gen, Mod, Hrl) ->
+ Name = case Gen of
+ #gen{erule=per,aligned=false} ->
+ "PER (unaligned)";
+ #gen{erule=per,aligned=true} ->
+ "PER (aligned)";
+ #gen{erule=ber} ->
+ "BER"
+ end,
+ emit(["%% Generated by the Erlang ASN.1 ",Name,
+ " compiler. Version: ",asn1ct:vsn(),nl,
+ "%% Purpose: Encoding and decoding of the types in ",
+ Mod,".",nl,nl,
+ "-module('",Mod,"').",nl,
+ "-compile(nowarn_unused_vars).",nl,
+ "-dialyzer(no_improper_lists).",nl]),
case Hrl of
0 -> ok;
- _ -> emit({"-include(\"",Mod,".hrl\").",nl})
+ _ -> emit(["-include(\"",Mod,".hrl\").",nl])
end,
emit(["-asn1_info([{vsn,'",asn1ct:vsn(),"'},",nl,
" {module,'",Mod,"'},",nl,
" {options,",io_lib:format("~p",[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,[H = #'ComponentType'{name=Cname}],Com,Extension) ->
- emit(Com),
- emit({asis,Cname}),
- gen_record_default(H, Extension);
-gen_record2(Name,SeqOrSet,[H = #'ComponentType'{name=Cname}|T],Com, Extension) ->
- emit(Com),
- emit({asis,Cname}),
- gen_record_default(H, Extension),
- gen_record2(Name,SeqOrSet,T,", ", Extension);
-gen_record2(Name,SeqOrSet,[_|T],Com,Extension) ->
- %% skip EXTENSIONMARK, ExtensionAdditionGroup and other markers
- gen_record2(Name,SeqOrSet,T,Com,Extension).
-
-gen_record_default(#'ComponentType'{prop='OPTIONAL'}, _)->
- emit(" = asn1_NOVALUE");
-gen_record_default(#'ComponentType'{prop={'DEFAULT',_}}, _)->
- emit(" = asn1_DEFAULT");
-gen_record_default(_, _) ->
- true.
+gen_hrlhead(Mod) ->
+ emit(["%% Generated by the Erlang ASN.1 compiler. Version: ",
+ asn1ct:vsn(),nl,
+ "%% Purpose: Erlang record definitions for each named and unnamed",nl,
+ "%% SEQUENCE and SET, and macro definitions for each value",nl,
+ "%% definition in module ",Mod,".",nl,nl]).
%% May only be a list or a two-tuple.
to_textual_order({Root,Ext}) ->
@@ -1585,27 +1503,19 @@ constructed_suffix('SEQUENCE OF',_) ->
constructed_suffix('SET OF',_) ->
'SETOF'.
-erule(ber) -> ber;
-erule(per) -> per;
-erule(uper) -> per.
-
index2suffix(0) ->
"";
index2suffix(N) ->
lists:concat(["_",N]).
-ct_gen_module(ber) ->
+ct_gen_module(#gen{erule=ber}) ->
asn1ct_gen_ber_bin_v2;
-ct_gen_module(per) ->
- asn1ct_gen_per;
-ct_gen_module(uper) ->
+ct_gen_module(#gen{erule=per}) ->
asn1ct_gen_per.
-ct_constructed_module(ber) ->
+ct_constructed_module(#gen{erule=ber}) ->
asn1ct_constructed_ber_bin_v2;
-ct_constructed_module(per) ->
- asn1ct_constructed_per;
-ct_constructed_module(uper) ->
+ct_constructed_module(#gen{erule=per}) ->
asn1ct_constructed_per.
get_constraint(C,Key) ->
@@ -1617,19 +1527,9 @@ get_constraint(C,Key) ->
{value,Cnstr} ->
Cnstr
end.
-
-get_record_name_prefix() ->
- case lists:keysearch(record_name_prefix,1,get(encoding_options)) of
- false ->
- "";
- {value,{_,Prefix}} ->
- Prefix
- end.
-get_macro_name_prefix() ->
- case lists:keysearch(macro_name_prefix,1,get(encoding_options)) of
- false ->
- "";
- {value,{_,Prefix}} ->
- Prefix
- end.
+get_record_name_prefix(#gen{rec_prefix=Prefix}) ->
+ Prefix.
+
+get_macro_name_prefix(#gen{macro_prefix=Prefix}) ->
+ Prefix.