aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src/asn1ct_constructed_per.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-11-29 06:48:47 +0100
committerBjörn Gustavsson <[email protected]>2012-12-06 14:22:37 +0100
commite958e6f5f9d95ce5828a2b858717512958b1f689 (patch)
tree90a47b729f03db0591e840af16c9f3568b8a122f /lib/asn1/src/asn1ct_constructed_per.erl
parent5af45916c69a5e3ad4027a06c56b5b620e05c283 (diff)
downloadotp-e958e6f5f9d95ce5828a2b858717512958b1f689.tar.gz
otp-e958e6f5f9d95ce5828a2b858717512958b1f689.tar.bz2
otp-e958e6f5f9d95ce5828a2b858717512958b1f689.zip
Refactor code generation for decoding SEQUENCE/SET
In order to optimize the generated code, we will need data structures that can be traversed in several passes before the actual code is generated. Refactor the code so that if first builds (essentially) a list of funs that do the actual code generation, and a second function that will call the funs one at the time.
Diffstat (limited to 'lib/asn1/src/asn1ct_constructed_per.erl')
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl799
1 files changed, 466 insertions, 333 deletions
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index 1558047e8f..d5afd20954 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -217,9 +217,44 @@ gen_decode_set(Erules,Typename,D) ->
gen_decode_sequence(Erules,Typename,D) ->
gen_decode_constructed(Erules,Typename,D).
-gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
+gen_decode_constructed(Erule, Typename, #type{}=D) ->
+ Imm = gen_dec_constructed_imm(Erule, Typename, #type{}=D),
asn1ct_name:start(),
asn1ct_name:clear(),
+ emit_gen_dec_imm(Imm),
+ emit([".",nl,nl]).
+
+emit_gen_dec_imm(L) ->
+ emit_gen_dec_imm(L, "", []).
+
+emit_gen_dec_imm([ignore|T], Sep, St) ->
+ emit_gen_dec_imm(T, Sep, St);
+emit_gen_dec_imm([{ignore,Fun}|T], Sep, St0) ->
+ St = Fun(St0),
+ emit_gen_dec_imm(T, Sep, St);
+emit_gen_dec_imm([{group,L}|T], Sep, St0) ->
+ emit(Sep),
+ St = emit_gen_dec_imm_group(L, St0),
+ emit_gen_dec_imm(T, [com,nl], St);
+emit_gen_dec_imm([Emit|T], Sep, St0) ->
+ emit(Sep),
+ St = Emit(St0),
+ emit_gen_dec_imm(T, [com,nl], St);
+emit_gen_dec_imm([], _, _) -> ok.
+
+emit_gen_dec_imm_group([H|T], St0) ->
+ St = emit_gen_dec_group_item(H, St0),
+ emit_gen_dec_imm_group(T, St);
+emit_gen_dec_imm_group([], St) -> St.
+
+emit_gen_dec_group_item(ignore, St) ->
+ St;
+emit_gen_dec_group_item({ignore,Fun}, St) ->
+ Fun(St);
+emit_gen_dec_group_item(Emit, St) ->
+ Emit(St).
+
+gen_dec_constructed_imm(Erule, Typename, #type{}=D) ->
{CompList,TableConsInfo} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
@@ -229,27 +264,29 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{CL,TCI} % the textual order is already taken care of
end,
Ext = extensible_dec(CompList),
- MaybeComma1 = case Ext of
- {ext,_Pos,_NumExt} ->
- gen_dec_extension_value("Bytes"),
- {",",nl};
- _ ->
- ""
- end,
+ EmitExt = case Ext of
+ {ext,_Pos,_NumExt} ->
+ fun(_) ->
+ gen_dec_extension_value("Bytes")
+ end;
+ _ -> ignore
+ end,
Optionals = optionals(CompList),
- MaybeComma2 = case Optionals of
- [] -> MaybeComma1;
- _ ->
- Bcurr = asn1ct_name:curr(bytes),
- Bnext = asn1ct_name:next(bytes),
- emit(MaybeComma1),
- GetoptCall = "} = ?RT_PER:getoptionals2(",
- emit({"{Opt,",{var,Bnext},GetoptCall,
- {var,Bcurr},",",{asis,length(Optionals)},")"}),
- asn1ct_name:new(bytes),
- ", "
- end,
- {DecObjInf,UniqueFName,ValueIndex} =
+ EmitOpt = case Optionals of
+ [] ->
+ ignore;
+ [_|_] ->
+ fun(_) ->
+ Bcurr = asn1ct_name:curr(bytes),
+ Bnext = asn1ct_name:next(bytes),
+ GetoptCall = "} = ?RT_PER:getoptionals2(",
+ emit({"{Opt,",{var,Bnext},GetoptCall,
+ {var,Bcurr},",",
+ {asis,length(Optionals)},")"}),
+ asn1ct_name:new(bytes)
+ end
+ end,
+ ObjSetInfo =
case TableConsInfo of
%% {ObjectSet,AttrN,N,UniqueFieldName} ->%% N is index of attribute that determines constraint
#simpletableattributes{objectsetname=ObjectSet,
@@ -281,13 +318,19 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{false,false,false}
end
end,
-%% NewCompList = wrap_compList(CompList),
- {AccTerm,AccBytes} =
- gen_dec_components_call(Erules,Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
- case asn1ct_name:all(term) of
- [] -> emit(MaybeComma2); % no components at all
- _ -> emit({com,nl})
- end,
+ {DecObjInf,_,_} = ObjSetInfo,
+ EmitComp = gen_dec_components_call(Erule, Typename, CompList,
+ DecObjInf, Ext, length(Optionals)),
+ EmitRest = fun({AccTerm,AccBytes}) ->
+ gen_dec_constructed_imm_2(Typename, CompList,
+ ObjSetInfo,
+ AccTerm, AccBytes)
+ end,
+ [EmitExt,EmitOpt|EmitComp++[EmitRest]].
+
+gen_dec_constructed_imm_2(Typename, CompList,
+ ObjSetInfo, AccTerm, AccBytes) ->
+ {_,UniqueFName,ValueIndex} = ObjSetInfo,
case {AccTerm,AccBytes} of
{[],[]} ->
ok;
@@ -329,8 +372,7 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
mkvlist(textual_order(to_encoding_order(CompList),asn1ct_name:all(term))),
emit("},")
end,
- emit({{curr,bytes},"}"}),
- emit({".",nl,nl}).
+ emit({{curr,bytes},"}"}).
textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) ->
TermList;
@@ -1002,53 +1044,66 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
emit("))");
_ -> true
end.
-gen_dec_components_call(Erule,TopType,{Root,ExtList},MaybeComma,
+
+gen_dec_components_call(Erule, TopType, {Root,ExtList},
+ DecInfObj, Ext, NumberOfOptionals) ->
+ gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},
+ DecInfObj,Ext,NumberOfOptionals);
+gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2},
DecInfObj,Ext,NumberOfOptionals) ->
- gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},MaybeComma,DecInfObj,Ext,NumberOfOptionals);
-gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
%% The type has extensionmarker
-
OptTable = create_optionality_table(Root1++Root2),
- {Rpos,AccTerm,AccBytes} =
- gen_dec_components_call1(Erule,TopType, Root1++Root2, 1, OptTable,
- MaybeComma,DecInfObj,noext,[],[],
- NumberOfOptionals),
- emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
- emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
- asn1ct_name:new(bytes),
+ Init = {ignore,fun(_) -> {[],[]} end},
+ {EmitRoot,Tpos} =
+ gen_dec_comp_calls(Root1++Root2, Erule, TopType, OptTable,
+ DecInfObj, noext, NumberOfOptionals,
+ 1, []),
+ EmitGetExt = fun(St) ->
+ emit(["{Extensions,",{next,bytes},"} = "]),
+ emit(["?RT_PER:getextension(Ext,",
+ {curr,bytes},")"]),
+ asn1ct_name:new(bytes),
+ St
+ end,
{extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL),
- NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen),
- {_Epos,AccTermE,AccBytesE} =
- gen_dec_components_call1(Erule,TopType,NewExtList,Rpos, OptTable,
- "",DecInfObj,Ext,[],[],NumberOfOptionals),
- case ExtList of
- [] -> true;
- _ -> emit([",",nl])
- end,
- emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",",
- length(ExtList)+1,",Extensions)",nl]),
- asn1ct_name:new(bytes),
- {AccTerm++AccTermE,AccBytes++AccBytesE};
-
-gen_dec_components_call(Erule,TopType,CompList,MaybeComma,DecInfObj,
- Ext,NumberOfOptionals) ->
+ NewExtList = wrap_extensionAdditionGroups(ExtList, ExtGroupPosLen),
+ {EmitExts,_} = gen_dec_comp_calls(NewExtList, Erule, TopType, OptTable,
+ DecInfObj, Ext, NumberOfOptionals,
+ Tpos, []),
+ Finish =
+ fun(St) ->
+ emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",",
+ length(ExtList)+1,",Extensions)"]),
+ asn1ct_name:new(bytes),
+ St
+ end,
+ [Init] ++ EmitRoot ++ [EmitGetExt|EmitExts] ++ [Finish];
+gen_dec_components_call(Erule, TopType, CompList, DecInfObj,
+ Ext, NumberOfOptionals) ->
%% The type has no extensionmarker
OptTable = create_optionality_table(CompList),
- {_,AccTerm,AccBytes} =
- gen_dec_components_call1(Erule,TopType, CompList, 1, OptTable,
- MaybeComma,DecInfObj,Ext,[],[],
- NumberOfOptionals),
- {AccTerm,AccBytes}.
-
-
-gen_dec_components_call1(Erule,TopType,
- [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop,textual_order=TextPos}|Rest],
- Tpos,OptTable,MaybeComma,DecInfObj,Ext,AccTerm,AccBytes,NumberOfOptionals) ->
+ Init = {ignore,fun(_) -> {[],[]} end},
+ {Cs,_} = gen_dec_comp_calls(CompList, Erule, TopType, OptTable,
+ DecInfObj, Ext, NumberOfOptionals,
+ 1, []),
+ [Init|Cs].
+
+gen_dec_comp_calls([C|Cs], Erule, TopType, OptTable, DecInfObj,
+ Ext, NumberOfOptionals, Tpos, Acc) ->
+ L = gen_dec_comp_call(C, Erule, TopType, Tpos, OptTable, DecInfObj,
+ Ext, NumberOfOptionals),
+ gen_dec_comp_calls(Cs, Erule, TopType, OptTable, DecInfObj,
+ Ext, NumberOfOptionals, Tpos+1, [L|Acc]);
+gen_dec_comp_calls([], _, _, _, _, _, _, Tpos, Acc) ->
+ {lists:append(lists:reverse(Acc)),Tpos}.
+
+gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj,
+ Ext, NumberOfOptionals) ->
+ #'ComponentType'{typespec=Type,prop=Prop,textual_order=TextPos} = Comp,
Pos = case Ext of
noext -> Tpos;
{ext,Epos,_Enum} -> Tpos - Epos + 1
end,
- emit(MaybeComma),
InnerType =
case Type#type.def of
#'ObjectClassFieldType'{type=InType} ->
@@ -1057,109 +1112,134 @@ gen_dec_components_call1(Erule,TopType,
asn1ct_gen:get_inner(Def)
end,
- case InnerType of
- #'Externaltypereference'{type=T} ->
- emit({nl,"%% attribute number ",TextPos," with type ",
- T,nl});
- IT when is_tuple(IT) ->
- emit({nl,"%% attribute number ",TextPos," with type ",
- element(2,IT),nl});
- _ ->
- emit({nl,"%% attribute number ",TextPos," with type ",
- InnerType,nl})
- end,
-
- IsMandatoryAndPredefinedTableC =
- fun(noext,mandatory,{"got objfun through args","ObjFun"}) ->
- true;
- (_,_,{"got objfun through args","ObjFun"}) ->
- false;
- (_,_,_) ->
- true
- end,
- case {InnerType,IsMandatoryAndPredefinedTableC(Ext,Prop,DecInfObj)} of
-%% {typefield,_} when Ext == noext, Prop == mandatory ->
- {{typefield,_},true} ->
- %% DecInfObj /= {"got objfun through args","ObjFun"} |
- %% (DecInfObj == {"got objfun through args","ObjFun"} &
- %% Ext == noext & Prop == mandatory)
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
+ DispType = case InnerType of
+ #'Externaltypereference'{type=T} -> T;
+ IT when is_tuple(IT) -> element(2,IT);
+ _ -> InnerType
+ end,
+ Comment = fun(St) ->
+ emit([nl,"%% attribute number ",TextPos,
+ " with type ",DispType,nl]),
+ St
+ end,
+
+ Preamble =
+ case {InnerType,is_mandatory_predef_tab_c(Ext, Prop, DecInfObj)} of
+ {{typefield,_},true} ->
+ %% DecInfObj /= {"got objfun through args","ObjFun"} |
+ %% (DecInfObj == {"got objfun through args","ObjFun"} &
+ %% Ext == noext & Prop == mandatory)
+ fun(St) ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
+ St
+ end;
%%{objectfield,_,_} when Ext == noext, Prop == mandatory ->
- {{objectfield,_,_},true} ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
+ {{objectfield,_,_},true} ->
+ fun(St) ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
+ St
+ end;
_ ->
case Type of
#type{def=#'SEQUENCE'{
extaddgroup=Number1,
components=ExtGroupCompList1}} when is_integer(Number1)->
- emit({"{{_,"}),
- emit_extaddgroupTerms(term,ExtGroupCompList1),
- emit({"}"});
+ fun(St) ->
+ emit(["{{_,"]),
+ emit_extaddgroupTerms(term,ExtGroupCompList1),
+ emit(["}"]),
+ emit([",",{next,bytes},"} = "]),
+ St
+ end;
_ ->
- asn1ct_name:new(term),
- emit({"{",{curr,term}})
- end,
- emit({",",{next,bytes},"} = "})
- end,
+ fun(St) ->
+ asn1ct_name:new(term),
+ emit(["{",{curr,term}]),
+ emit([",",{next,bytes},"} = "]),
+ St
+ end
+ end
+ end,
- case {Ext,Prop,is_optimized(Erule)} of
- {noext,mandatory,_} -> ok; % generate nothing
- {noext,_,_} -> %% OPTIONAL or DEFAULT
- OptPos = get_optionality_pos(TextPos,OptTable),
- Element = io_lib:format("Opt band (1 bsl ~w)",[NumberOfOptionals - OptPos]),
- emit(["case ",Element," of",nl]),
- emit([" _Opt",TextPos," when _Opt",TextPos," > 0 ->"]);
+ OptOrDef =
+ case {Ext,Prop,is_optimized(Erule)} of
+ {noext,mandatory,_} ->
+ ignore;
+ {noext,_,_} -> %% OPTIONAL or DEFAULT
+ OptPos = get_optionality_pos(TextPos, OptTable),
+ Element = io_lib:format("Opt band (1 bsl ~w)",
+ [NumberOfOptionals - OptPos]),
+ fun(St) ->
+ emit(["case ",Element," of",nl]),
+ emit([" _Opt",TextPos," when _Opt",TextPos," > 0 ->"]),
+ St
+ end;
{_,_,false} -> %% extension element, not bitstring
- emit(["case Extensions of",nl]),
- emit([" _ when size(Extensions) >= ",Pos,",element(",Pos,",Extensions) == 1 ->",nl]);
- _ ->
- emit(["case Extensions of",nl]),
- emit([" <<_:",Pos-1,",1:1,_/bitstring>> when bit_size(Extensions) >= ",Pos," ->",nl])
- end,
- put(component_type,{true,C}),
- {TermVar,BytesVar} = gen_dec_line(Erule,TopType,Cname,Type,Tpos,DecInfObj,Ext,Prop),
- erase(component_type),
- case {Ext,Prop} of
- {noext,mandatory} -> true; % generate nothing
- {noext,_} ->
- emit([";",nl,"0 ->"]),
- emit(["{"]),
- gen_dec_component_no_val(Ext,Prop),
- emit({",",{curr,bytes},"}",nl}),
- emit([nl,"end"]);
- _ ->
- emit([";",nl,"_ ->",nl]),
- emit(["{"]),
- case Type of
- #type{def=#'SEQUENCE'{
- extaddgroup=Number2,
- components=ExtGroupCompList2}} when is_integer(Number2)->
- emit({"{extAddGroup,"}),
- gen_dec_extaddGroup_no_val(Ext,ExtGroupCompList2),
- emit({"}"});
- _ ->
- gen_dec_component_no_val(Ext,Prop)
- end,
- emit({",",{curr,bytes},"}",nl}),
- emit([nl,"end"])
- end,
- asn1ct_name:new(bytes),
- case Rest of
- [] ->
- {Tpos+1,AccTerm++TermVar,AccBytes++BytesVar};
- _ ->
- emit({com,nl}),
- gen_dec_components_call1(Erule,TopType,Rest,Tpos+1,OptTable,
- "",DecInfObj,Ext, AccTerm++TermVar,
- AccBytes++BytesVar,NumberOfOptionals)
- end;
-
-gen_dec_components_call1(_,_TopType,[],Pos,_OptTable,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
- {Pos,AccTerm,AccBytes}.
+ fun(St) ->
+ emit(["case Extensions of",nl]),
+ emit([" _ when size(Extensions) >= ",Pos,
+ ",element(",Pos,",Extensions) == 1 ->",nl]),
+ St
+ end;
+ _ ->
+ fun(St) ->
+ emit(["case Extensions of",nl]),
+ emit([" <<_:",Pos-1,",1:1,_/bitstring>> "
+ "when bit_size(Extensions) >= ",Pos," ->",nl]),
+ St
+ end
+ end,
+ Lines = gen_dec_line_imm(Erule, TopType, Comp, Tpos, DecInfObj, Ext),
+ Postamble =
+ case {Ext,Prop} of
+ {noext,mandatory} ->
+ ignore;
+ {noext,_} ->
+ fun(St) ->
+ emit([";",nl,"0 ->"]),
+ emit(["{"]),
+ gen_dec_component_no_val(Ext,Prop),
+ emit({",",{curr,bytes},"}",nl}),
+ emit([nl,"end"]),
+ St
+ end;
+ _ ->
+ fun(St) ->
+ emit([";",nl,"_ ->",nl]),
+ emit(["{"]),
+ case Type of
+ #type{def=#'SEQUENCE'{
+ extaddgroup=Number2,
+ components=ExtGroupCompList2}}
+ when is_integer(Number2)->
+ emit({"{extAddGroup,"}),
+ gen_dec_extaddGroup_no_val(Ext,ExtGroupCompList2),
+ emit({"}"});
+ _ ->
+ gen_dec_component_no_val(Ext, Prop)
+ end,
+ emit({",",{curr,bytes},"}",nl}),
+ emit([nl,"end"]),
+ St
+ end
+ end,
+ AdvBuffer = {ignore,fun(St) ->
+ asn1ct_name:new(bytes),
+ St
+ end},
+ [{group,[Comment,Preamble,OptOrDef|Lines]++[Postamble,AdvBuffer]}].
+
+is_mandatory_predef_tab_c(noext, mandatory,
+ {"got objfun through args","ObjFun"}) ->
+ true;
+is_mandatory_predef_tab_c(_, _, {"got objfun through args","ObjFun"}) ->
+ false;
+is_mandatory_predef_tab_c(_,_,_) ->
+ true.
gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}])->
gen_dec_component_no_val(Ext,Prop),
@@ -1179,8 +1259,14 @@ gen_dec_component_no_val({ext,_,_},mandatory) ->
emit({"asn1_NOVALUE"}).
-gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) ->
- Ctgenmod = asn1ct_gen:ct_gen_module(Erule),
+gen_dec_line(Erule, TopType, Comp, Pos, DecInfObj, Ext) ->
+ Imm0 = gen_dec_line_imm(Erule, TopType, Comp, Pos, DecInfObj, Ext),
+ Init = {ignore,fun(_) -> {[],[]} end},
+ Imm = [{group,[Init|Imm0]}],
+ emit_gen_dec_imm(Imm).
+
+gen_dec_line_imm(Erule, TopType, Comp, Pos, DecInfObj, Ext) ->
+ #'ComponentType'{name=Cname,typespec=Type} = Comp,
Atype =
case Type of
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
@@ -1189,177 +1275,230 @@ gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) ->
asn1ct_gen:get_inner(Type#type.def)
end,
- BytesVar0 = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- BytesVar = case Ext of
- {ext,Ep,_} when Pos >= Ep ->
- emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,
- "}=?RT_PER:decode_open_type(",
- {curr,bytes},",[]),",nl,
- "{TmpValx",Pos,",_}="]),
- io_lib:format("TmpVal~p",[Pos]);
- _ -> BytesVar0
- end,
- SaveBytes =
- case Atype of
- {typefield,_} ->
+ Pre = gen_dec_line_open_type(Ext, Pos),
+ Decode = gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj, Ext),
+ Post =
+ fun({SaveBytes,Finish}) ->
+ {AccTerm,AccBytes} = Finish(),
+ #'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- false -> % This is in a choice with typefield components
- {Name,RestFieldNames} =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
- emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
- "} = ?RT_PER:decode_open_type(",{curr,bytes},
- ", []),",nl]),
- emit([indent(2),"case (catch ObjFun(",
- {asis,Name},",",{curr,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"]),
- [];
- {"got objfun through args","ObjFun"} ->
- %% this is when the generated code gots the
- %% objfun though arguments on function
- %% invocation.
- if
- Ext == noext andalso Prop == mandatory ->
- ok;
- true ->
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(tmpbytes),
- emit([nl," {",{curr,tmpterm},", ",{curr,tmpbytes},"} ="])
- end,
- {Name,RestFieldNames} =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- emit(["?RT_PER:decode_open_type(",{curr,bytes},
- ", []),",nl]),
- if
- Ext == noext andalso 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
- Ext == noext andalso Prop == mandatory ->
- ok;
- true ->
- emit([",",nl,{curr,tmpbytes},"}"])
- end,
- [];
+ {Cname,ObjSet} ->
+ ObjSetRef =
+ case ObjSet of
+ {deep,OSName,_,_} ->
+ OSName;
+ _ -> ObjSet
+ end,
+ {AccTerm++[{ObjSetRef,Cname,
+ asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
+ AccBytes++SaveBytes};
_ ->
- emit(["?RT_PER:decode_open_type(",{curr,bytes},
- ", [])"]),
- RefedFieldName =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ {AccTerm,AccBytes++SaveBytes}
+ end
+ end,
+ [Pre,Decode,Post].
+
+gen_dec_line_open_type({ext,Ep,_}, Pos) when Pos >= Ep ->
+ fun(St) ->
+ emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,"} = ",
+ "?RT_PER:decode_open_type(",
+ {curr,bytes},", []),",nl,
+ "{TmpValx",Pos,",_}="]),
+ {"TmpVal" ++ integer_to_list(Pos),
+ fun() ->
+ emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]),
+ St
+ end}
+ end;
+gen_dec_line_open_type(_, _) ->
+ fun(St) ->
+ {asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ fun() -> St end}
+ end.
- [{Cname,RefedFieldName,
+gen_dec_line_special(_, {typefield,_}, _TopType, Comp,
+ DecInfObj, Ext) ->
+ #'ComponentType'{name=Cname,typespec=Type,prop=Prop} = Comp,
+ fun({_BytesVar,PrevSt}) ->
+ case DecInfObj of
+ false -> % This is in a choice with typefield components
+ {Name,RestFieldNames} =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(reason),
+ emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
+ "} = ?RT_PER:decode_open_type(",{curr,bytes},
+ ", []),",nl]),
+ emit([indent(2),"case (catch ObjFun(",
+ {asis,Name},",",{curr,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"]),
+ {[],PrevSt};
+ {"got objfun through args","ObjFun"} ->
+ %% this is when the generated code gots the
+ %% objfun though arguments on function
+ %% invocation.
+ if
+ Ext == noext andalso Prop == mandatory ->
+ ok;
+ true ->
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(tmpbytes),
+ emit([nl," {",{curr,tmpterm},", ",{curr,tmpbytes},"} ="])
+ end,
+ {Name,RestFieldNames} =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ emit(["?RT_PER:decode_open_type(",{curr,bytes},
+ ", []),",nl]),
+ if
+ Ext == noext andalso 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
+ Ext == noext andalso Prop == mandatory ->
+ ok;
+ true ->
+ emit([",",nl,{curr,tmpbytes},"}"])
+ end,
+ {[],PrevSt};
+ _ ->
+ emit(["?RT_PER:decode_open_type(",{curr,bytes},
+ ", [])"]),
+ RefedFieldName =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+
+ {[{Cname,RefedFieldName,
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ Prop}],PrevSt}
+ end
+ end;
+gen_dec_line_special(_, {objectfield,PrimFieldName1,PFNList}, _TopType,
+ Comp, _DecInfObj, _Ext) ->
+ fun({_BytesVar,PrevSt}) ->
+ emit(["?RT_PER:decode_open_type(",{curr,bytes},", [])"]),
+ #'ComponentType'{name=Cname,prop=Prop} = Comp,
+ SaveBytes = [{Cname,{PrimFieldName1,PFNList},
asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- get_components_prop()}]
- end;
- {objectfield,PrimFieldName1,PFNList} ->
- emit(["?RT_PER:decode_open_type(",{curr,bytes},", [])"]),
- [{Cname,{PrimFieldName1,PFNList},
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- get_components_prop()}];
- _ ->
- CurrMod = get(currmod),
- case asn1ct_gen:type(Atype) of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- emit({"'dec_",EType,"'(",BytesVar,",telltype)"});
- #'Externaltypereference'{module=Mod,type=EType} ->
- emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
- ",telltype)"});
- {primitive,bif} ->
- case Atype of
- {fixedtypevaluefield,_,Btype} ->
- Ctgenmod:gen_dec_prim(Erule,Btype,
- BytesVar);
- _ ->
- Ctgenmod:gen_dec_prim(Erule,Type,
- BytesVar)
- end;
- 'ASN1_OPEN_TYPE' ->
- case Type#type.def of
- #'ObjectClassFieldType'{type=OpenType} ->
- Ctgenmod:gen_dec_prim(Erule,#type{def=OpenType},
- BytesVar);
- _ ->
- Ctgenmod:gen_dec_prim(Erule,Type,
- BytesVar)
- end;
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(",BytesVar,",telltype)"});
- {notype,_} ->
- emit({"'dec_",Atype,"'(",BytesVar,",telltype)"});
- {constructed,bif} ->
- NewTypename = [Cname|TopType],
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype, ObjFun)"});
- _ ->
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype)"})
- end
- end,
- case DecInfObj of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
- Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- ValueMatch = value_match(ValIndex,Term),
- {ObjSetMod,ObjSetName} =
- case OSet of
- {M,O} -> {{asis,M},O};
- _ -> {"?MODULE",OSet}
- end,
- emit({",",nl,"ObjFun = ",ObjSetMod,
- ":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,")"});
- _ ->
- ok
- end,
- []
- end,
- case Ext of
- {ext,Ep2,_} when Pos >= Ep2 ->
- emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]);
- _ -> true
- end,
- %% Prepare return value
+ Prop}],
+ {SaveBytes,PrevSt}
+ end;
+gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj, _Ext) ->
+ case gen_dec_line_other(Erule, Atype, TopType, Comp) of
+ Fun when is_function(Fun, 1) ->
+ fun({BytesVar,PrevSt}) ->
+ Fun(BytesVar),
+ gen_dec_line_dec_inf(Comp, DecInfObj),
+ {[],PrevSt}
+ end
+ end.
+
+gen_dec_line_dec_inf(Comp, DecInfObj) ->
+ #'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- {Cname,ObjSet} ->
- ObjSetRef =
- case ObjSet of
- {deep,OSName,_,_} ->
- OSName;
- _ -> ObjSet
+ {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ ValueMatch = value_match(ValIndex,Term),
+ {ObjSetMod,ObjSetName} =
+ case OSet of
+ {M,O} -> {{asis,M},O};
+ _ -> {"?MODULE",OSet}
end,
- {[{ObjSetRef,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
- SaveBytes};
+ emit({",",nl,"ObjFun = ",ObjSetMod,
+ ":'getdec_",ObjSetName,"'(",
+ {asis,UniqueFName},", ",ValueMatch,")"});
_ ->
- {[],SaveBytes}
+ ok
+ end.
+
+gen_dec_line_other(Erule, Atype, TopType, Comp) ->
+ #'ComponentType'{name=Cname,typespec=Type} = Comp,
+ CurrMod = get(currmod),
+ Ctgenmod = asn1ct_gen:ct_gen_module(Erule),
+ case asn1ct_gen:type(Atype) of
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ fun(BytesVar) ->
+ emit({"'dec_",EType,"'(",BytesVar,",telltype)"})
+ end;
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ fun(BytesVar) ->
+ emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
+ ",telltype)"})
+ end;
+ {primitive,bif} ->
+ case Atype of
+ {fixedtypevaluefield,_,Btype} ->
+ fun(BytesVar) ->
+ Ctgenmod:gen_dec_prim(Erule, Btype,
+ BytesVar)
+ end;
+ _ ->
+ fun(BytesVar) ->
+ Ctgenmod:gen_dec_prim(Erule, Type,
+ BytesVar)
+ end
+ end;
+ 'ASN1_OPEN_TYPE' ->
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OpenType} ->
+ fun(BytesVar) ->
+ Ctgenmod:gen_dec_prim(Erule,#type{def=OpenType},
+ BytesVar)
+ end;
+ _ ->
+ fun(BytesVar) ->
+ Ctgenmod:gen_dec_prim(Erule, Type,
+ BytesVar)
+ end
+ end;
+ #typereference{val=Dname} ->
+ fun(BytesVar) ->
+ emit({"'dec_",Dname,"'(",BytesVar,",telltype)"})
+ end;
+ {notype,_} ->
+ fun(BytesVar) ->
+ emit({"'dec_",Atype,"'(",BytesVar,",telltype)"})
+ end;
+ {constructed,bif} ->
+ NewTypename = [Cname|TopType],
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ fun(BytesVar) ->
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(",BytesVar,", telltype, ObjFun)"})
+ end;
+ _ ->
+ fun(BytesVar) ->
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(",BytesVar,", telltype)"})
+ end
+ end
end.
+
gen_enc_choice(Erule,TopType,CompList,Ext) ->
gen_enc_choice_tag(CompList, [], Ext),
emit({com,nl}),
@@ -1611,18 +1750,12 @@ wrap_extensionAdditionGroups([],_,Acc,_,_) ->
lists:reverse(Acc).
-wrap_gen_dec_line(Erule,C,TopType,Cname,Type,Pos,DIO,Ext) ->
+wrap_gen_dec_line(Erule,C,TopType,_Cname,_Type,Pos,DIO,Ext) ->
put(component_type,{true,C}),
- gen_dec_line(Erule,TopType,Cname,Type,Pos,DIO,Ext,mandatory),
+ gen_dec_line(Erule, TopType, C#'ComponentType'{prop=mandatory},
+ Pos, DIO, Ext),
erase(component_type).
-get_components_prop() ->
- case get(component_type) of
- undefined ->
- mandatory;
- {true,#'ComponentType'{prop=Prop}} -> Prop
- end.
-
value_match(Index,Value) when is_atom(Value) ->
value_match(Index,atom_to_list(Value));