aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2013-07-01 09:05:37 +0200
committerBjörn Gustavsson <[email protected]>2013-09-03 16:00:15 +0200
commitdf7bb30fd0e8161e5146705fd117aa0bb115fbe7 (patch)
treefad34f34add6e9822052a513c4524cdf4f47e311
parenteb49ee71f0751cf54bc39f9971f389c92525b0a4 (diff)
downloadotp-df7bb30fd0e8161e5146705fd117aa0bb115fbe7.tar.gz
otp-df7bb30fd0e8161e5146705fd117aa0bb115fbe7.tar.bz2
otp-df7bb30fd0e8161e5146705fd117aa0bb115fbe7.zip
PER, UPER: Optimize table constraints
The generated code for table constraints has several problems: * For each object set, a function for getting an encoding or decoding fun is generated, regardless of whether it is actually used. In many specifications, the object set actually used is the union of several other object sets. That means that the code can become a lot bulkier than it would need to be. * The funs are not necessary. The funs just add to the code bloat and generate more unnecessary garbage at run-time. Also, one of the arguments of the fun is the name of the field in the class which is known at compile-time, and the fun for decoding has unused arguments. How to fix the problems: At each call site where an open type should be encoded/decoded, call a specific generated function specialized for the actual object set and the name of the field in the class. When generating the specialized functions, make sure that we re-use a previously generated function if possible.
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl425
-rw-r--r--lib/asn1/src/asn1ct_gen.erl18
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl634
-rw-r--r--lib/asn1/src/asn1ct_imm.erl3
4 files changed, 318 insertions, 762 deletions
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index 68edcfd109..d8df0b58e8 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -43,8 +43,13 @@ gen_encode_set(Erules,TypeName,D) ->
gen_encode_sequence(Erules,TypeName,D) ->
gen_encode_constructed(Erules,TypeName,D).
-gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
+gen_encode_constructed(Erule, Typename, #type{}=D) ->
asn1ct_name:start(),
+ Imm = gen_encode_constructed_imm(Erule, Typename, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl]).
+
+gen_encode_constructed_imm(Erule, Typename, #type{}=D) ->
{ExtAddGroup,TmpCompList,TableConsInfo} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL,extaddgroup=ExtAddGroup0} ->
@@ -112,10 +117,7 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
El = make_element(N+1, asn1ct_gen:mk_var(asn1ct_name:curr(val))),
ValueMatch = value_match(ValueIndex, El),
- GetEnc = enc_func("getenc_", ObjSetName),
- ObjSetImm0 = [{apply,{Module,GetEnc},
- [{expr,ValueMatch}],
- {var,ObjectEncode}}],
+ ObjSetImm0 = [{assign,{var,ObjectEncode},ValueMatch}],
{{AttrN,ObjectEncode},ObjSetImm0};
false ->
{false,[]}
@@ -141,10 +143,8 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
[]
end,
ImmBody = gen_enc_components_call(Erule, Typename, CompList, EncObj, Ext),
- Imm = ExternalImm ++ ExtImm ++ ObjSetImm ++
- asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody),
- asn1ct_imm:enc_cg(Imm, Aligned),
- emit([".",nl]).
+ ExternalImm ++ ExtImm ++ ObjSetImm ++
+ asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody).
gen_encode_extaddgroup(CompList) ->
case extgroup_pos_and_length(CompList) of
@@ -308,13 +308,14 @@ gen_dec_constructed_imm(Erule, Typename, #type{}=D) ->
EmitComp = gen_dec_components_call(Erule, Typename, CompList,
DecObjInf, Ext, length(Optionals)),
EmitRest = fun({AccTerm,AccBytes}) ->
- gen_dec_constructed_imm_2(Typename, CompList,
+ gen_dec_constructed_imm_2(Erule, Typename,
+ CompList,
ObjSetInfo,
AccTerm, AccBytes)
end,
[EmitExt,EmitOpt|EmitComp++[{safe,EmitRest}]].
-gen_dec_constructed_imm_2(Typename, CompList,
+gen_dec_constructed_imm_2(Erule, Typename, CompList,
ObjSetInfo, AccTerm, AccBytes) ->
{_,_UniqueFName,ValueIndex} = ObjSetInfo,
case {AccTerm,AccBytes} of
@@ -323,13 +324,13 @@ gen_dec_constructed_imm_2(Typename, CompList,
{_,[]} ->
ok;
{[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} = ObjSet,
- emit([DecObj," =",nl,
- " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
- ValueMatch,"),",nl]),
- gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
+ ValueMatch = value_match(ValueIndex, Term),
+ _ = [begin
+ gen_dec_open_type(Erule, ValueMatch, ObjSet,
+ LeadingAttr, T),
+ emit([com,nl])
+ end || T <- ListOfOpenTypes],
+ ok
end,
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
demit({"Result = "}), %dbg
@@ -403,57 +404,143 @@ to_textual_order(Cs) when is_list(Cs) ->
to_textual_order(Cs) ->
Cs.
-gen_dec_listofopentypes(_,[],_) ->
- emit(nl);
-gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
-
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
-
- emit([Term," = ",nl]),
-
- N = case Prop of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
-
- emit([indent(N+3),"case (catch ",DecObj,"(",
- {asis,FirstPFN},", ",TmpTerm,", telltype,",{asis,PFNList},")) of",nl]),
- emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
- emit([indent(N+9),"exit({'Type not compatible with table constraint',",
- {curr,reason},"});",nl]),
- emit([indent(N+6),"{",{curr,tmpterm},",_} ->",nl]),
- emit([indent(N+9),{curr,tmpterm},nl]),
-
- case Prop of
- mandatory ->
- emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
- gen_dec_listofopentypes(DecObj,Rest,true).
-
+gen_dec_open_type(Erule, Val, {Xmod,Xtype}, LeadingAttr,
+ {_,{Name,RestFieldNames},Term,TmpTerm,Prop}) ->
+ #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype),
+ #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0,
+ #'Externaltypereference'{module=ClMod,type=ClType} = Class,
+ #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType),
+ #objectclass{fields=ClassFields} = ClassDef,
+ Extensible = lists:member('EXTENSIONMARK', ObjSet1),
+ ObjSet2 = [{Key,fix_object_code(Name, Code, ClassFields)} ||
+ {_,Key,Code} <- ObjSet1],
+ ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]),
+ Key = erlang:md5(term_to_binary({decode,ObjSet,RestFieldNames,
+ Prop,Extensible})),
+ Typename = [Name,ClType],
+ Gen = fun(_Fd, N) ->
+ dec_objset_optional(N, Prop),
+ dec_objset(Erule, N, ObjSet, RestFieldNames, Typename),
+ dec_objset_default(N, Name, LeadingAttr, Extensible)
+ end,
+ Prefix = lists:concat(["dec_os_",Name]),
+ F = asn1ct_func:call_gen(Prefix, Key, Gen),
+ emit([Term," = ",{asis,F},"(",TmpTerm,", ",Val,")"]).
+
+dec_objset_optional(N, {'DEFAULT',Val}) ->
+ dec_objset_optional_1(N, Val),
+ dec_objset_optional_1(N, asn1_DEFAULT);
+dec_objset_optional(N, 'OPTIONAL') ->
+ dec_objset_optional_1(N, asn1_NOVALUE);
+dec_objset_optional(_N, mandatory) -> ok.
+
+dec_objset_optional_1(N, Val) ->
+ emit([{asis,N},"(",{asis,Val},", _Id) ->",nl,
+ {asis,Val},";",nl]).
+
+dec_objset(_Erule, _N, [], _, _) ->
+ ok;
+dec_objset(Erule, N, [Obj|Objs], RestFields, Cl) ->
+ dec_objset_1(Erule, N, Obj, RestFields, Cl),
+ emit([";",nl]),
+ dec_objset(Erule, N, Objs, RestFields, Cl).
+
+dec_objset_default(N, C, LeadingAttr, false) ->
+ emit([{asis,N},"(Bytes, Id) ->",nl,
+ "exit({'Type not compatible with table constraint',"
+ "{{component,",{asis,C},"},"
+ "{value,Bytes},"
+ "{unique_name_and_value,",{asis,LeadingAttr},",Id}}}).",nl,nl]);
+dec_objset_default(N, _, _, true) ->
+ emit([{asis,N},"(Bytes, Id) ->",nl,
+ "Bytes.",nl,nl]).
+
+dec_objset_1(Erule, N, {Id,Obj}, RestFields, Typename) ->
+ emit([{asis,N},"(Bytes, ",{asis,Id},") ->",nl]),
+ dec_objset_2(Erule, Obj, RestFields, Typename).
+
+dec_objset_2(Erule, Obj, RestFields0, Typename) ->
+ case Obj of
+ #typedef{name={primitive,bif},typespec=Type} ->
+ Imm = asn1ct_gen_per:gen_dec_imm(Erule, Type),
+ {Term,_} = asn1ct_imm:dec_slim_cg(Imm, 'Bytes'),
+ emit([com,nl,Term]);
+ #typedef{name={constructed,bif},typespec=Def} ->
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'CHOICE' ->
+ asn1ct_name:start(),
+ asn1ct_name:new(bytes),
+ {'CHOICE',CompList} = Def#type.def,
+ Ext = extensible_enc(CompList),
+ emit(["{Result,_} = begin",nl]),
+ gen_dec_choice(Erule, Typename, CompList, Ext),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SET' ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, Def),
+ Imm = opt_imm(Imm0),
+ asn1ct_name:start(),
+ emit(["{Result,_} = begin",nl]),
+ emit_gen_dec_imm(Imm),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SET OF' ->
+ asn1ct_name:start(),
+ do_gen_decode_sof(Erule, Typename, 'SET OF',
+ Def, false);
+ 'SEQUENCE' ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, Def),
+ Imm = opt_imm(Imm0),
+ asn1ct_name:start(),
+ emit(["{Result,_} = begin",nl]),
+ emit_gen_dec_imm(Imm),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SEQUENCE OF' ->
+ asn1ct_name:start(),
+ do_gen_decode_sof(Erule, Typename, 'SEQUENCE OF',
+ Def, false)
+ end;
+ #typedef{name=Type} ->
+ emit(["{Result,_} = ",{asis,enc_func("dec_", Type)},"(Bytes),",nl,
+ "Result"]);
+ #'Externaltypereference'{module=Mod,type=Type} ->
+ emit("{Term,_} = "),
+ Func = enc_func("dec_", Type),
+ case get(currmod) of
+ Mod ->
+ emit([{asis,Func},"(Bytes)"]);
+ _ ->
+ emit([{asis,Mod},":",{asis,Func},"(Bytes)"])
+ end,
+ emit([com,nl,
+ "Term"]);
+ #'Externalvaluereference'{module=Mod,value=Value} ->
+ case asn1_db:dbget(Mod, Value) of
+ #typedef{typespec=#'Object'{def=Def}} ->
+ {object,_,Fields} = Def,
+ [NextField|RestFields] = RestFields0,
+ {NextField,Typedef} = lists:keyfind(NextField, 1, Fields),
+ dec_objset_2(Erule, Typedef, RestFields, Typename)
+ end
+ end.
-emit_opt_or_mand_check(Val,Term) ->
- emit([indent(3),"case ",Term," of",nl,
- indent(6),{asis,Val}," ->",{asis,Val},";",nl,
- indent(6),"_ ->",nl]).
+gen_encode_choice(Erule, TopType, D) ->
+ asn1ct_name:start(),
+ Imm = gen_encode_choice_imm(Erule, TopType, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl]).
-gen_encode_choice(Erule, TopType, #type{def={'CHOICE',CompList}}) ->
- emit(["{ChoiceTag,ChoiceVal} = Val,",nl,
- ""]),
+gen_encode_choice_imm(Erule, TopType, #type{def={'CHOICE',CompList}}) ->
Ext = extensible_enc(CompList),
Aligned = is_aligned(Erule),
Cs = gen_enc_choice(Erule, TopType, CompList, Ext),
- Imm = asn1ct_imm:per_enc_choice('ChoiceTag', Cs, Aligned),
- asn1ct_imm:enc_cg(Imm, Aligned),
- emit([".",nl]).
+ [{assign,{expr,"{ChoiceTag,ChoiceVal}"},"Val"}|
+ asn1ct_imm:per_enc_choice('ChoiceTag', Cs, Aligned)].
gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
@@ -466,9 +553,13 @@ gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Encode generator for SEQUENCE OF type
-
-gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
+gen_encode_sof(Erule, Typename, SeqOrSetOf, D) ->
asn1ct_name:start(),
+ Imm = gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl,nl]).
+
+gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, #type{}=D) ->
{_SeqOrSetOf,ComponentType} = D#type.def,
Aligned = is_aligned(Erule),
Constructed_Suffix =
@@ -496,12 +587,14 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
#type{def='ASN1_OPEN_TYPE'},
Aligned)
end,
- Imm = asn1ct_imm:per_enc_sof('Val', D#type.constraint, 'Comp', Imm0, Aligned),
- asn1ct_imm:enc_cg(Imm, Aligned),
- emit([".",nl,nl]).
+ asn1ct_imm:per_enc_sof('Val', D#type.constraint, 'Comp', Imm0, Aligned).
-gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
+gen_decode_sof(Erules, Typename, SeqOrSetOf, #type{}=D) ->
asn1ct_name:start(),
+ do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D, true),
+ emit([".",nl,nl]).
+
+do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D, NeedRest) ->
{_SeqOrSetOf,ComponentType} = D#type.def,
SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
D#type.constraint),
@@ -513,15 +606,16 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
""
end,
{Num,Buf} = gen_decode_length(SizeConstraint, Erules),
- Key = erlang:md5(term_to_binary({Typename,SeqOrSetOf,ComponentType})),
+ Key = erlang:md5(term_to_binary({Typename,SeqOrSetOf,
+ ComponentType,NeedRest})),
Gen = fun(_Fd, Name) ->
gen_decode_sof_components(Erules, Name,
Typename, SeqOrSetOf,
- ComponentType)
+ ComponentType, NeedRest)
end,
F = asn1ct_func:call_gen("dec_components", Key, Gen),
emit([",",nl,
- {asis,F},"(",Num,", ",Buf,ObjFun,", []).",nl,nl]).
+ {asis,F},"(",Num,", ",Buf,ObjFun,", [])"]).
is_aligned(per) -> true;
is_aligned(uper) -> false.
@@ -531,7 +625,7 @@ gen_decode_length(Constraint, Erule) ->
Imm = asn1ct_imm:per_dec_length(Constraint, true, is_aligned(Erule)),
asn1ct_imm:dec_slim_cg(Imm, "Bytes").
-gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont) ->
+gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont, NeedRest) ->
{ObjFun,ObjFun_Var} =
case Cont#type.tablecinf of
[{objfun,_}|_R] ->
@@ -539,9 +633,15 @@ gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont) ->
_ ->
{"",""}
end,
- emit([{asis,Name},"(0, Bytes",ObjFun_Var,", Acc) ->",nl,
- "{lists:reverse(Acc),Bytes};",nl,
- {asis,Name},"(Num, Bytes",ObjFun,", Acc) ->",nl,
+ case NeedRest of
+ false ->
+ emit([{asis,Name},"(0, _Bytes",ObjFun_Var,", Acc) ->",nl,
+ "lists:reverse(Acc);",nl]);
+ true ->
+ emit([{asis,Name},"(0, Bytes",ObjFun_Var,", Acc) ->",nl,
+ "{lists:reverse(Acc),Bytes};",nl])
+ end,
+ emit([{asis,Name},"(Num, Bytes",ObjFun,", Acc) ->",nl,
"{Term,Remain} = "]),
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
Cont#type.def),
@@ -825,8 +925,8 @@ gen_enc_line_imm_1(Erule, TopType, Cname, Type, Element, DynamicEnc) ->
{_LeadingAttrName,Fun} = DynamicEnc,
case (Type#type.def)#'ObjectClassFieldType'.fieldname of
{Name,RestFieldNames} when is_atom(Name) ->
- Imm = [{apply,{var,Fun},
- [Name,{expr,Element},RestFieldNames]}],
+ Imm = enc_var_type_call(Erule, Name, RestFieldNames,
+ Type, Fun, Element),
asn1ct_imm:per_enc_open_type(Imm, Aligned)
end;
_ ->
@@ -867,6 +967,108 @@ enc_func(Type) ->
enc_func(Prefix, Name) ->
list_to_atom(lists:concat([Prefix,Name])).
+enc_var_type_call(Erule, Name, RestFieldNames,
+ #type{tablecinf=TCI}, Fun, Val) ->
+ [{objfun,#'Externaltypereference'{module=Xmod,type=Xtype}}] = TCI,
+ #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype),
+ #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0,
+ #'Externaltypereference'{module=ClMod,type=ClType} = Class,
+ #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType),
+ #objectclass{fields=ClassFields} = ClassDef,
+ Extensible = lists:member('EXTENSIONMARK', ObjSet1),
+ ObjSet2 = [{Key,fix_object_code(Name, Code, ClassFields)} ||
+ {_,Key,Code} <- ObjSet1],
+ ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]),
+ Key = erlang:md5(term_to_binary({encode,ObjSet,RestFieldNames,Extensible})),
+ Gen = fun(_Fd, N) ->
+ enc_objset(Erule, Name, N, ObjSet,
+ RestFieldNames, Extensible)
+ end,
+ Prefix = lists:concat(["enc_os_",Name]),
+ F = asn1ct_func:call_gen(Prefix, Key, Gen),
+ [{apply,F,[{var,atom_to_list(Val)},{var,Fun}]}].
+
+fix_object_code(Name, [{Name,B}|_], _ClassFields) ->
+ B;
+fix_object_code(Name, [_|T], ClassFields) ->
+ fix_object_code(Name, T, ClassFields);
+fix_object_code(Name, [], ClassFields) ->
+ case lists:keyfind(Name, 2, ClassFields) of
+ {typefield,Name,'OPTIONAL'} ->
+ none;
+ {objectfield,Name,_,_,'OPTIONAL'} ->
+ none;
+ {typefield,Name,{'DEFAULT',#type{}=Type}} ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ #typedef{name={primitive,bif},typespec=Type};
+ {constructed,bif} ->
+ #typedef{name={constructed,bif},typespec=Type}
+ end
+ end.
+
+
+enc_objset(Erule, Component, Name, ObjSet, RestFieldNames, Extensible) ->
+ asn1ct_name:start(),
+ Aligned = is_aligned(Erule),
+ E = {error,
+ fun() ->
+ emit(["exit({'Type not compatible with table constraint',"
+ "{component,",{asis,Component},"},"
+ "{value,Val},"
+ "{unique_name_and_value,'_'}})",nl])
+ end},
+ Imm = [{'cond',
+ [[{eq,{var,"Id"},Key}|
+ enc_obj(Erule, Obj, RestFieldNames, Aligned)] ||
+ {Key,Obj} <- ObjSet] ++
+ [['_',case Extensible of
+ false -> E;
+ true -> {put_bits,{var,"Val"},binary,[1]}
+ end]]}],
+ emit([{asis,Name},"(Val, Id) ->",nl]),
+ asn1ct_imm:enc_cg(Imm, Aligned),
+ emit([".",nl]).
+
+enc_obj(Erule, Obj, RestFieldNames0, Aligned) ->
+ case Obj of
+ #typedef{name={primitive,bif},typespec=Def} ->
+ asn1ct_gen_per:gen_encode_prim_imm('Val', Def, Aligned);
+ #typedef{name={constructed,bif},typespec=Def} ->
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'CHOICE' ->
+ gen_encode_choice_imm(Erule, name, Def);
+ 'SET' ->
+ gen_encode_constructed_imm(Erule, name, Def);
+ 'SET OF' ->
+ gen_encode_sof_imm(Erule, name, InnerType, Def);
+ 'SEQUENCE' ->
+ gen_encode_constructed_imm(Erule, name, Def);
+ 'SEQUENCE OF' ->
+ gen_encode_sof_imm(Erule, name, InnerType, Def)
+ end;
+ #typedef{name=Type} ->
+ [{apply,enc_func(Type),[{var,"Val"}]}];
+ #'Externalvaluereference'{module=Mod,value=Value} ->
+ case asn1_db:dbget(Mod, Value) of
+ #typedef{typespec=#'Object'{def=Def}} ->
+ {object,_,Fields} = Def,
+ [NextField|RestFieldNames] = RestFieldNames0,
+ {NextField,Typedef} = lists:keyfind(NextField, 1, Fields),
+ enc_obj(Erule, Typedef, RestFieldNames, Aligned)
+ end;
+ #'Externaltypereference'{module=Mod,type=Type} ->
+ Func = enc_func(Type),
+ case get(currmod) of
+ Mod ->
+ [{apply,Func,[{var,"Val"}]}];
+ _ ->
+ [{apply,{Mod,Func},[{var,"Val"}]}]
+ end
+ end.
+
gen_dec_components_call(Erule, TopType, {Root,ExtList},
DecInfObj, Ext, NumberOfOptionals) ->
@@ -1152,25 +1354,19 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
false -> % This is in a choice with typefield components
{Name,RestFieldNames} =
(Type#type.def)#'ObjectClassFieldType'.fieldname,
-
- asn1ct_name:new(reason),
Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
{TmpTerm,TempBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar),
+ emit([com,nl]),
+ #type{tablecinf=[{objfun,
+ #'Externaltypereference'{module=Xmod,
+ type=Xtype}}]} =
+ Type,
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ 'Result',TmpTerm,mandatory}),
emit([com,nl,
- {next,bytes}," = ",TempBuf,com,nl,
- indent(2),"case (catch ObjFun(",
- {asis,Name},",",TmpTerm,",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),"{",{asis,Cname},", {",{curr,tmpterm},", ",
- {next,bytes},"}}",nl]),
- emit([indent(2),"end"]),
+ "{",{asis,Cname},",{Result,",TempBuf,"}}"]),
{[],PrevSt};
{"got objfun through args","ObjFun"} ->
%% this is when the generated code gots the
@@ -1190,27 +1386,22 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
asn1ct_imm:dec_code_gen(Imm, BytesVar),
emit([com,nl]),
+ #type{tablecinf=[{objfun,
+ #'Externaltypereference'{module=Xmod,
+ type=Xtype}}]} =
+ Type,
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ TmpTerm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
if
Prop =:= mandatory ->
- emit([{curr,term}," =",nl," "]);
- true ->
- emit([" {"])
- end,
- emit(["case (catch ObjFun(",{asis,Name},",",
- {curr,tmpterm},",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([" {'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),{curr,tmpterm},nl]),
- emit([indent(2),"end"]),
- if
- Prop =:= mandatory ->
- ok;
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ Term,TmpTerm,Prop});
true ->
+ emit([" {"]),
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ '_',TmpTerm,Prop}),
emit([",",nl,{curr,tmpbytes},"}"])
end,
{[],PrevSt};
@@ -1247,14 +1438,11 @@ gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj) ->
gen_dec_line_dec_inf(Comp, DecInfObj) ->
#'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- {Cname,{_,OSet,_UniqueFName,ValIndex}} ->
+ {Cname,{_,_OSet,_UniqueFName,ValIndex}} ->
Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
ValueMatch = value_match(ValIndex,Term),
- {ObjSetMod,ObjSetName} = OSet,
emit([",",nl,
- "ObjFun = ",{asis,ObjSetMod},
- ":'getdec_",ObjSetName,"'(",
- ValueMatch,")"]);
+ "ObjFun = ",ValueMatch]);
_ ->
ok
end.
@@ -1474,9 +1662,6 @@ gen_dec_choice2(Erule, TopType, [H0|T], Pos, Sep0, Pre) ->
gen_dec_choice2(Erule, TopType, T, Pos+1, Sep, Pre);
gen_dec_choice2(_, _, [], _, _, _) -> ok.
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
make_elements(I,Val,ExtCnames) ->
make_elements(I,Val,ExtCnames,[]).
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index fa05aacb95..e6ec0cb12b 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -824,10 +824,7 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
_ ->
case erule(Erules) of
per ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",3),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",4);
+ ok;
ber ->
emit({"-export([",nl}),
gen_exports1(Objects,"enc_",3),
@@ -838,10 +835,15 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
case ObjectSets of
[] -> ok;
_ ->
- emit({"-export([",nl}),
- gen_exports1(ObjectSets, "getenc_",1),
- emit({"-export([",nl}),
- gen_exports1(ObjectSets, "getdec_",1)
+ 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(),
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 2063cb12e5..8b999ddbf0 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -186,615 +186,14 @@ simplify_type(Type) ->
%% Object code generating for encoding and decoding
%% ------------------------------------------------
-gen_obj_code(Erules,_Module,Obj) when is_record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=Mod,type=ClassName} =
- Def#'Object'.classname,
- Class = asn1_db:dbget(Mod,ClassName),
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
- gen_encode_objectfields(Erules, ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
- gen_decode_objectfields(Erules, ClassName, get_class_fields(Class),
- ObjName, Fields, []),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed),
- emit(nl).
-
-
-gen_encode_objectfields(Erule, ClassName,
- [{typefield,Name,OptOrMand}|Rest],
- ObjName, ObjectFields, ConstrAcc) ->
- EmitFuncClause =
- fun(V) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",V,",_RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, _RestPrimFieldName) ->",nl]),
- MaybeConstr =
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'OPTIONAL'} ->
- EmitFuncClause("Val"),
- emit(" Val"),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val"),
- gen_encode_default_call(Erule, ClassName, Name, DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val"),
- gen_encode_field_call(Erule, ObjName, Name, TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(Erule,ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(Erule,ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- CurrentMod = get(currmod),
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_"),
- emit([" exit({error,{'use of missing field in object', ",{asis,Name},
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,#'Externalvaluereference'{module=CurrentMod,
- value=TypeName}},_} ->
- EmitFuncClause(" Val, [H|T]"),
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"});
- {{Name,#'Externalvaluereference'{module=M,value=TypeName}},_} ->
- EmitFuncClause(" Val, [H|T]"),
- emit({indent(3),"'",M,"':'enc_",TypeName,"'(H, Val, T)"});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Val,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(Erule,ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(Erule,ClassName,[_C|Cs],O,OF,Acc) ->
- gen_encode_objectfields(Erule,ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_, _,[],_,_,Acc) ->
- Acc.
-
-
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ ->
-%% FuncName = list_to_atom(lists:concat(["enc_",TypeDef#typedef.name])),
- FuncName = asn1ct_gen:list2rname(TypeDef#typedef.name ++ [enc]),
- emit(["'",FuncName,"'(Val) ->",nl]),
- Def = TypeDef#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_encode_constructed(Erules,TypeDef#typedef.name,
- InnerType,Def),
- gen_encode_constr_type(Erules,Rest)
- end;
-gen_encode_constr_type(_,[]) ->
+gen_obj_code(_Erules, _Module, #typedef{}) ->
ok.
-gen_encode_field_call(_Erules, _ObjName, _FieldName,
- #'Externaltypereference'{module=M,type=T}) ->
- CurrentMod = get(currmod),
- if
- M == CurrentMod ->
- emit({" 'enc_",T,"'(Val)"}),
- [];
- true ->
- emit({" '",M,"':'enc_",T,"'(Val)"}),
- []
- end;
-gen_encode_field_call(Erules, ObjName, FieldName, Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_encode_prim(Erules, Def, "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val)"}),
-%% [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- [Type#typedef{name=[FieldName,ObjName]}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val)"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val)"}),
- []
- end.
-
-gen_encode_default_call(Erules, ClassName, FieldName, Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Val)"]),
-%% [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- [#typedef{name=[FieldName,ClassName],
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(Erules, Type, "Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val)",nl]),
- []
- end.
-
-
-gen_decode_objectfields(Erules, ClassName,
- [{typefield,Name,OptOrMand}|Rest],
- ObjName, ObjectFields, ConstrAcc) ->
- EmitFuncClause =
- fun(Bytes) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
- ",_,_RestPrimFieldName) ->",nl])
- end,
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'OPTIONAL'} ->
- EmitFuncClause("Bytes"),
- emit([" {Bytes,[]}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes"),
- gen_decode_default_call(Erules, ClassName, Name, "Bytes",
- DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes"),
- gen_decode_field_call(Erules, ObjName, Name, "Bytes", TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(Erules, ClassName, Rest, ObjName,
- ObjectFields, MaybeConstr++ConstrAcc);
-gen_decode_objectfields(Erules, ClassName,
- [{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName, ObjectFields, ConstrAcc) ->
- CurrentMod = get(currmod),
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,_,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",{asis,Name},
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,#'Externalvaluereference'{module=CurrentMod,
- value=TypeName}},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"});
- {{Name,#'Externalvaluereference'{module=M,value=TypeName}},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- emit({indent(3),"'",M,"':'dec_",TypeName,
- "'(H, Bytes, telltype, T)"});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, telltype, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(Erules, ClassName, Rest, ObjName,
- ObjectFields, ConstrAcc);
-gen_decode_objectfields(Erules, CN, [_C|Cs], O, OF, CAcc) ->
- gen_decode_objectfields(Erules, CN, Cs, O, OF, CAcc);
-gen_decode_objectfields(_, _, [], _, _, CAcc) ->
- CAcc.
-
-
-
-gen_decode_field_call(_Erules, _ObjName, _FieldName, Bytes,
- #'Externaltypereference'{}=Etype) ->
- emit(" "),
- gen_dec_external(Etype, Bytes),
- [];
-gen_decode_field_call(Erules, ObjName, FieldName, Bytes, Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_dec_prim(Erules, Def, Bytes),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,")"}),
-%% [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- [Type#typedef{name=[FieldName,ObjName]}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,")"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,")"}),
- []
- end.
-
-gen_decode_default_call(Erules, ClassName, FieldName, Bytes, Type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- DecFunc = dec_func(lists:concat([ClassName,'_',FieldName])),
- emit([" ",{asis,DecFunc},"(",Bytes,")"]),
- [#typedef{name=[FieldName,ClassName],
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(Erules, Type, Bytes),
- [];
- #'Externaltypereference'{}=Etype ->
- asn1ct_gen_per:gen_dec_external(Etype, Bytes),
- []
- end.
-
-
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef#typedef{name=asn1ct_gen:list2rname(TypeDef#typedef.name)})
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-
-more_genfields([]) ->
- false;
-more_genfields([Field|Fields]) ->
- case element(1,Field) of
- typefield ->
- true;
- objectfield ->
- true;
- _ ->
- more_genfields(Fields)
- end.
-
%% Object Set code generating for encoding and decoding
%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-%% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
- InternalFuncs=
- gen_objset_enc(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
- gen_objset_dec(Erules, ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erules,InternalFuncs).
-
-%% gen_objset_enc iterates over the objects of the object set
-gen_objset_enc(_,_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(Erule, ObjSetName, UniqueName, [{ObjName,Val,Fields}|T],
- ClName, ClFields, NthObj, Acc)->
- emit(["'getenc_",ObjSetName,"'(",{asis,Val},") ->",nl]),
- CurrMod = get(currmod),
- {InternalFunc,NewNthObj}=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_enc_funs(Erule, Fields, ClFields,
- ObjSetName, NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],NthObj};
- {ModName,Name} ->
- emit_ext_encfun(ModName,Name),
- {[],NthObj};
- _Other ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(Erule, ObjSetName, UniqueName, T, ClName, ClFields,
- NewNthObj, InternalFunc ++ Acc);
-gen_objset_enc(_, ObjSetName, _UniqueName, ['EXTENSIONMARK'],
- _ClName, _ClFields, _NthObj, Acc) ->
- emit(["'getenc_",ObjSetName,"'(_) ->",nl]),
- emit({indent(3),"fun(_, Val, _) ->",nl}),
- emit([indent(6),"Val",nl,
- indent(3),"end.",nl,nl]),
- Acc;
-gen_objset_enc(_, ObjSetName, UniqueName, [], _, _, _, Acc) ->
- emit_default_getenc(ObjSetName, UniqueName),
- emit([".",nl,nl]),
- Acc.
-
-emit_ext_encfun(ModuleName,Name) ->
- emit([indent(4),"fun(T,V,O) -> '",ModuleName,"':'enc_",
- Name,"'(T,V,O) end"]).
-
-emit_default_getenc(ObjSetName,UniqueName) ->
- emit(["'getenc_",ObjSetName,"'(ErrV) ->",nl]),
- emit([indent(4),"fun(C,V,_) -> exit({'Type not compatible with table constraint',{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]).
-
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Erule, Fields, [{typefield,_,_}|_]=T,
- ObjSetName, NthObj) ->
- emit([indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl]),
- gen_inlined_enc_funs1(Erule, Fields, T, ObjSetName, [], NthObj, []);
-gen_inlined_enc_funs(Erule,Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Erule,Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_,_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Erule, Fields, [{typefield,Name,_}|Rest], ObjSetName,
- Sep0, NthObj, Acc0) ->
- emit(Sep0),
- Sep = [";",nl],
- CurrentMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc,NAdd} =
- case lists:keyfind(Name, 1, Fields) of
- {_,#type{}=Type} ->
- {Ret,N} = emit_inner_of_fun(Erule, Type, InternalDefFunName),
- {Ret++Acc0,N};
- {_,#typedef{}=Type} ->
- emit([indent(9),{asis,Name}," ->",nl]),
- {Ret,N} = emit_inner_of_fun(Erule, Type, InternalDefFunName),
- {Ret++Acc0,N};
- {_,#'Externaltypereference'{module=CurrentMod,type=T}} ->
- emit([indent(9),{asis,Name}," ->",nl,
- indent(12),"'enc_",T,"'(Val)"]),
- {Acc0,0};
- {_,#'Externaltypereference'{module=M,type=T}} ->
- emit([indent(9),{asis,Name}," ->",nl,
- indent(12),"'",M,"'",":'enc_",T,"'(Val)"]),
- {Acc0,0};
- false ->
- emit([indent(9),{asis,Name}," ->",nl,
- indent(12),"Val",nl]),
- {Acc0,0}
- end,
- gen_inlined_enc_funs1(Erule, Fields, Rest, ObjSetName, Sep,
- NthObj+NAdd, Acc);
-gen_inlined_enc_funs1(Erule, Fields, [_|T], ObjSetName, Sep, NthObj, Acc)->
- gen_inlined_enc_funs1(Erule, Fields, T, ObjSetName, Sep, NthObj, Acc);
-gen_inlined_enc_funs1(_, _, [], _, _, NthObj, Acc) ->
- emit([nl,indent(6),"end",nl,
- indent(3),"end"]),
- {Acc,NthObj}.
-
-emit_inner_of_fun(Erule, #typedef{name={ExtMod,Name},typespec=Type}=TDef,
- InternalDefFunName) ->
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(Erule, Type, "Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val)"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
- {[],0}
- end;
-emit_inner_of_fun(_Erule, #typedef{name=Name}, _) ->
- emit({indent(12),"'enc_",Name,"'(Val)"}),
- {[],0};
-emit_inner_of_fun(Erule, #type{}=Type, _) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when is_atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(Erule, Type, "Val");
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val)"})
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_, _, {unique,undefined}, _, _, _, _) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(Erule, ObjSName, UniqueName, [{ObjName,Val,Fields}|T], ClName,
- ClFields, NthObj)->
- emit(["'getdec_",ObjSName,"'(",{asis,Val},") ->",nl]),
- CurrMod = get(currmod),
- NewNthObj=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Erule, Fields, ClFields,
- ObjSName, NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/4"]),
- NthObj;
- {ModName,Name} ->
- emit_ext_decfun(ModName,Name),
- NthObj;
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- gen_objset_dec(Erule, ObjSName, UniqueName, T, ClName, ClFields, NewNthObj);
-gen_objset_dec(_Erule, ObjSetName, _UniqueName, ['EXTENSIONMARK'],
- _ClName, _ClFields, _NthObj) ->
- emit(["'getdec_",ObjSetName,"'(_) ->",nl]),
- emit({indent(3),"fun(Attr1, Bytes, _,_) ->",nl}),
- emit({indent(6),"{Bytes,Attr1}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(_Erule, ObjSetName, UniqueName, [], _, _, _) ->
- emit_default_getdec(ObjSetName, UniqueName),
- emit([".",nl,nl]),
+gen_objectset_code(_Erules, _ObjSet) ->
ok.
-emit_ext_decfun(ModuleName,Name) ->
- emit([indent(3),"fun(T,V,O1,O2) -> '",ModuleName,"':'dec_",
- Name,"'(T,V,O1,O2) end"]).
-
-emit_default_getdec(ObjSetName,UniqueName) ->
- emit(["'getdec_",ObjSetName,"'(ErrV) ->",nl]),
- emit([indent(2), "fun(C,V,_,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]).
-
-
-gen_inlined_dec_funs(Erule, Fields, List, ObjSetName, NthObj0) ->
- emit([indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl]),
- NthObj = gen_inlined_dec_funs1(Erule, Fields, List,
- ObjSetName, "", NthObj0),
- emit([nl,indent(6),"end",nl,
- indent(3),"end"]),
- NthObj.
-
-gen_inlined_dec_funs1(Erule, Fields, [{typefield,Name,_}|Rest],
- ObjSetName, Sep0, NthObj) ->
- InternalDefFunName = [NthObj,Name,ObjSetName],
- emit(Sep0),
- Sep = [";",nl],
- N = case lists:keyfind(Name, 1, Fields) of
- {_,#type{}=Type} ->
- emit_inner_of_decfun(Erule, Type, InternalDefFunName);
- {_,#typedef{}=Type} ->
- emit([indent(9),{asis,Name}," ->",nl]),
- emit_inner_of_decfun(Erule, Type, InternalDefFunName);
- {_,#'Externaltypereference'{}=Etype} ->
- emit([indent(9),{asis,Name}," ->",nl,
- indent(12)]),
- gen_dec_external(Etype, "Val"),
- 0;
- false ->
- emit([indent(9),{asis,Name}," -> {Val,Type}"]),
- 0
- end,
- gen_inlined_dec_funs1(Erule, Fields, Rest, ObjSetName, Sep, NthObj+N);
-gen_inlined_dec_funs1(Erule, Fields, [_|Rest], ObjSetName, Sep, NthObj) ->
- gen_inlined_dec_funs1(Erule, Fields, Rest, ObjSetName, Sep, NthObj);
-gen_inlined_dec_funs1(_, _, [], _, _, NthObj) -> NthObj.
-
-emit_inner_of_decfun(Erule, #typedef{name={ExtName,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(Erule, Type, "Val"),
- 0;
- {constructed,bif} ->
- emit({indent(12),"'dec_",
- asn1ct_gen:list2name(InternalDefFunName),"'(Val)"}),
- 1;
- _ ->
- emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Val)"}),
- 0
- end;
-emit_inner_of_decfun(_Erule, #typedef{name=Name}, _) ->
- emit({indent(12),"'dec_",Name,"'(Val)"}),
- 0;
-emit_inner_of_decfun(Erule, #type{}=Type, _) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when is_atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(Erule, Type, "Val");
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
- T,"'(Val)"})
- end,
- 0.
-
-
-gen_internal_funcs(_,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,"'(Bytes) ->",nl]),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-
%% DECODING *****************************
%%***************************************
@@ -979,35 +378,6 @@ gen_dec_prim(Erule, Type, BytesVar) ->
Imm = gen_dec_imm(Erule, Type),
asn1ct_imm:dec_code_gen(Imm, BytesVar).
-is_already_generated(Operation,Name) ->
- case get(class_default_type) of
- undefined ->
- put(class_default_type,[{Operation,Name}]),
- false;
- GeneratedList ->
- case lists:member({Operation,Name},GeneratedList) of
- true ->
- true;
- false ->
- put(class_default_type,[{Operation,Name}|GeneratedList]),
- false
- end
- end.
-
-get_class_fields(#classdef{typespec=ObjClass}) ->
- ObjClass#objectclass.fields;
-get_class_fields(#objectclass{fields=Fields}) ->
- Fields;
-get_class_fields(_) ->
- [].
-
-
-get_object_field(Name,ObjectFields) ->
- case lists:keysearch(Name,1,ObjectFields) of
- {value,Field} -> Field;
- false -> false
- end.
-
%% For PER the ExtensionAdditionGroup notation has significance for the encoding and decoding
%% the components within the ExtensionAdditionGroup is treated in a similar way as if they
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index 44282b4b55..7994889a38 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -1680,8 +1680,6 @@ enc_cg({apply,F0,As0,Dst}) ->
As = enc_call_args(As0, ""),
emit([mk_val(Dst)," = "]),
case F0 of
- {var,F} ->
- emit([F,"(",As,")"]);
{M,F} ->
emit([{asis,M},":",{asis,F},"(",As,")"]);
F when is_atom(F) ->
@@ -2028,6 +2026,7 @@ enc_opt_al_cond_1([[C|Act0]|Cs0], Al0, CAcc, AAcc) ->
enc_opt_al_cond_1(Cs0, Al0, [[C|Act]|CAcc], [Al|AAcc]);
enc_opt_al_cond_1([], _, CAcc, AAcc) ->
Al = case lists:usort(AAcc) of
+ [] -> unknown;
[Al0] -> Al0;
[_|_] -> unknown
end,