aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1/src/asn1ct_gen_ber_bin_v2.erl')
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl532
1 files changed, 167 insertions, 365 deletions
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index de0adef2b2..8ab49aec2c 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -24,9 +24,7 @@
-include("asn1_records.hrl").
--export([pgen/4]).
-export([decode_class/1, decode_type/1]).
--export([add_removed_bytes/0]).
-export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
-export([gen_encode_prim/4]).
-export([gen_dec_prim/7]).
@@ -59,18 +57,6 @@
-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
-%% pgen(Erules, Module, TypeOrVal)
-%% 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,PTypeList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
-
-
%%===============================================================================
%%===============================================================================
%%===============================================================================
@@ -83,8 +69,8 @@ pgen(OutFile,Erules,Module,TypeOrVal) ->
%% encode #{typedef, {pos, name, typespec}}
%%===============================================================================
-gen_encode(Erules,Type) when is_record(Type,typedef) ->
- gen_encode_user(Erules,Type).
+gen_encode(Erules, #typedef{}=D) ->
+ gen_encode_user(Erules, #typedef{}=D, true).
%%===============================================================================
%% encode #{type, {tag, def, constraint}}
@@ -134,20 +120,28 @@ gen_encode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
NewType = Type#type{tag=[]},
gen_encode(Erules,NewTname,NewType).
-gen_encode_user(Erules,D) when is_record(D,typedef) ->
+gen_encode_user(Erules, #typedef{}=D, Wrapper) ->
Typename = [D#typedef.name],
Type = D#typedef.typespec,
InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
emit([nl,nl,"%%================================"]),
emit([nl,"%% ",Typename]),
emit([nl,"%%================================",nl]),
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, ", {asis,lists:reverse(Tag)},").",nl,nl]),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn) ->",nl}),
+ FuncName = "'enc_" ++ asn1ct_gen:list2name(Typename) ++ "'",
+ case Wrapper of
+ true ->
+ %% This is a top-level type. Generate an 'enc_Type'/1
+ %% wrapper.
+ OTag = Type#type.tag,
+ Tag0 = [encode_tag_val(decode_class(Class), Form, Number) ||
+ #tag{class=Class,form=Form,number=Number} <- OTag],
+ Tag = lists:reverse(Tag0),
+ emit([FuncName,"(Val) ->",nl,
+ " ",FuncName,"(Val, ",{asis,Tag},").",nl,nl]);
+ false ->
+ ok
+ end,
+ emit([FuncName,"(Val, TagIn) ->",nl]),
CurrentMod = get(currmod),
case asn1ct_gen:type(InnerType) of
{constructed,bif} ->
@@ -155,8 +149,6 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
{primitive,bif} ->
gen_encode_prim(ber,Type,"TagIn","Val"),
emit([".",nl]);
- #typereference{val=Ename} ->
- emit([" 'enc_",Ename,"'(Val, TagIn).",nl]);
#'Externaltypereference'{module=CurrentMod,type=Etype} ->
emit([" 'enc_",Etype,"'(Val, TagIn).",nl]);
#'Externaltypereference'{module=Emod,type=Etype} ->
@@ -169,8 +161,8 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
emit([".",nl])
end.
-gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
- BitStringConstraint = D#type.constraint,
+gen_encode_prim(_Erules, #type{}=D, DoTag, Value) ->
+ BitStringConstraint = get_size_constraint(D#type.constraint),
asn1ct_name:new(enumval),
Type = case D#type.def of
'OCTET STRING' -> restricted_string;
@@ -184,6 +176,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
'GeneralString' -> restricted_string;
'PrintableString' -> restricted_string;
'IA5String' -> restricted_string;
+ 'UTCTime' -> restricted_string;
+ 'GeneralizedTime' -> restricted_string;
Other -> Other
end,
case Type of
@@ -208,8 +202,6 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
call(encode_bit_string,
[{asis,BitStringConstraint},Value,
{asis,NamedNumberList},DoTag]);
- 'ANY' ->
- call(encode_open_type, [Value,DoTag]);
'NULL' ->
call(encode_null, [Value,DoTag]);
'OBJECT IDENTIFIER' ->
@@ -222,19 +214,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
call(encode_UTF8_string, [Value,DoTag]);
'BMPString' ->
call(encode_BMP_string, [Value,DoTag]);
- 'UTCTime' ->
- call(encode_utc_time, [Value,DoTag]);
- 'GeneralizedTime' ->
- call(encode_generalized_time, [Value,DoTag]);
'ASN1_OPEN_TYPE' ->
- call(encode_open_type, [Value,DoTag]);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(D#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_encode_prim(Erules,InnerType,DoTag,Value);
- 'ASN1_OPEN_TYPE' ->
- call(encode_open_type, [Value,DoTag])
- end
+ call(encode_open_type, [Value,DoTag])
end.
emit_enc_enumerated_cases({L1,L2}, Tags) ->
@@ -470,32 +451,18 @@ gen_decode_user(Erules,D) when is_record(D,typedef) ->
end.
-gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
+gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) ->
Typename = Att#type.def,
%% Currently not used for BER replaced with [] as place holder
%% Constraint = Att#type.constraint,
%% Constraint = [],
- Constraint =
- case get_constraint(Att#type.constraint,'SizeConstraint') of
- no -> [];
- Tc -> Tc
- end,
- ValueRange =
- case get_constraint(Att#type.constraint,'ValueRange') of
- no -> [];
- Tv -> Tv
- end,
- SingleValue =
- case get_constraint(Att#type.constraint,'SingleValue') of
- no -> [];
- Sv -> Sv
- end,
+ Constraint = get_size_constraint(Att#type.constraint),
+ IntConstr = int_constr(Att#type.constraint),
AsBin = case get(binary_strings) of
true -> "_as_bin";
_ -> ""
end,
NewTypeName = case Typename of
- 'ANY' -> 'ASN1_OPEN_TYPE';
'OCTET STRING' -> restricted_string;
'NumericString' -> restricted_string;
'TeletexString' -> restricted_string;
@@ -506,6 +473,9 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
'GeneralString' -> restricted_string;
'PrintableString' -> restricted_string;
'IA5String' -> restricted_string;
+ 'ObjectDescriptor'-> restricted_string;
+ 'UTCTime' -> restricted_string;
+ 'GeneralizedTime' -> restricted_string;
_ -> Typename
end,
case NewTypeName of
@@ -513,14 +483,27 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
emit(["decode_boolean(",BytesVar,","]),
need(decode_boolean, 2);
'INTEGER' ->
- emit(["decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},","]),
- need(decode_integer, 3);
+ case IntConstr of
+ [] ->
+ emit(["decode_integer(",BytesVar,","]),
+ need(decode_integer, 2);
+ {_,_} ->
+ emit(["decode_integer(",BytesVar,",",
+ {asis,IntConstr},","]),
+ need(decode_integer, 3)
+ end;
{'INTEGER',NamedNumberList} ->
- emit(["decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},",",
- {asis,NamedNumberList},","]),
- need(decode_integer, 4);
+ case IntConstr of
+ [] ->
+ emit(["decode_named_integer(",BytesVar,",",
+ {asis,NamedNumberList},","]),
+ need(decode_named_integer, 3);
+ {_,_} ->
+ emit(["decode_named_integer(",BytesVar,",",
+ {asis,IntConstr},",",
+ {asis,NamedNumberList},","]),
+ need(decode_named_integer, 4)
+ end;
{'ENUMERATED',NamedNumberList} ->
emit(["decode_enumerated(",BytesVar,",",
{asis,NamedNumberList},","]),
@@ -538,10 +521,6 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
'RELATIVE-OID' ->
emit(["decode_relative_oid(",BytesVar,","]),
need(decode_relative_oid, 2);
- 'ObjectDescriptor' ->
- emit(["decode_restricted_string(",
- BytesVar,",",{asis,Constraint},","]),
- need(decode_restricted_string, 3);
restricted_string ->
emit(["decode_restricted_string",AsBin,"(",BytesVar,","]),
case Constraint of
@@ -563,31 +542,10 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
emit(["decode_BMP_string",AsBin,"(",
BytesVar,",",{asis,Constraint},","]),
need(decode_BMP_string, 3);
- 'UTCTime' ->
- emit(["decode_utc_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","]),
- need(decode_utc_time, 3);
- 'GeneralizedTime' ->
- emit(["decode_generalized_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","]),
- need(decode_generalized_time, 3);
'ASN1_OPEN_TYPE' ->
emit(["decode_open_type_as_binary(",
BytesVar,","]),
- need(decode_open_type_as_binary, 2);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_dec_prim(Erules,InnerType,BytesVar,DoTag,TagIn,Form,OptOrMand);
- 'ASN1_OPEN_TYPE' ->
- emit(["decode_open_type_as_binary(",
- BytesVar,","]),
- need(decode_open_type_as_binary, 2);
- Other ->
- exit({'cannot decode',Other})
- end;
- Other ->
- exit({'cannot decode',Other})
+ need(decode_open_type_as_binary, 2)
end,
TagStr = case DoTag of
@@ -604,25 +562,27 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
{call,ber,match_tags,[BytesVar,TagStr]},com,nl,
{call,real_common,decode_real,[{curr,tmpbuf}]},nl,
"end",nl]);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- 'ASN1_OPEN_TYPE' ->
- emit([TagStr,")"]);
- _ -> ok
- end;
_ ->
emit([TagStr,")"])
end.
-
-int_constr([],[]) ->
- [];
-int_constr([],ValueRange) ->
- ValueRange;
-int_constr(SingleValue,[]) ->
- SingleValue;
-int_constr(SV,VR) ->
- [SV,VR].
+%% Simplify an integer constraint so that we can efficiently test it.
+-spec int_constr(term()) -> [] | {integer(),integer()|'MAX'}.
+int_constr(C) ->
+ case asn1ct_imm:effective_constraint(integer, C) of
+ [{_,[]}] ->
+ %% Extension - ignore constraint.
+ [];
+ [{'ValueRange',{'MIN',_}}] ->
+ %% Tricky to implement efficiently - ignore it.
+ [];
+ [{'ValueRange',{_,_}=Range}] ->
+ Range;
+ [{'SingleValue',Sv}] ->
+ {Sv,Sv};
+ [] ->
+ []
+ end.
gen_dec_bit_string(BytesVar, _Constraint, [_|_]=NNL, TagStr) ->
call(decode_named_bit_string,
@@ -664,9 +624,7 @@ gen_obj_code(Erules,_Module,Obj) when is_record(Obj,typedef) ->
ObjName,Fields,[]),
emit(nl),
gen_decode_constr_type(Erules,DecConstructed),
- emit_tlv_format_function();
-gen_obj_code(_Erules,_Module,Obj) when is_record(Obj,pobjectdef) ->
- ok.
+ emit_tlv_format_function().
gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
ObjName,ObjectFields,ConstrAcc) ->
@@ -757,7 +715,7 @@ gen_encode_objectfields(_,[],_,_,Acc) ->
gen_encode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
case is_already_generated(enc,TypeDef#typedef.name) of
true -> ok;
- _ -> gen_encode_user(Erules,TypeDef)
+ false -> gen_encode_user(Erules, TypeDef, false)
end,
gen_encode_constr_type(Erules,Rest);
gen_encode_constr_type(_,[]) ->
@@ -815,8 +773,8 @@ gen_encode_default_call(ClassName,FieldName,Type) ->
Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
case asn1ct_gen:type(InnerType) of
{constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes)"]),
+ emit([" 'enc_",ClassName,'_',FieldName,"'",
+ "(Val, ",{asis,Tag},")"]),
[#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
typespec=Type}];
{primitive,bif} ->
@@ -964,7 +922,10 @@ 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)
+ emit([nl,nl,
+ "'dec_",TypeDef#typedef.name,
+ "'(Tlv, TagIn) ->",nl]),
+ gen_decode_user(Erules, TypeDef)
end,
gen_decode_constr_type(Erules,Rest);
gen_decode_constr_type(_,[]) ->
@@ -1108,54 +1069,29 @@ 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(Erules,ObjSName,UniqueName,
- [{ObjName,Val,Fields},T|Rest],ClName,ClFields,
+gen_objset_enc(Erules, ObjSetName, UniqueName,
+ [{ObjName,Val,Fields}|T], ClName, ClFields,
NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
+ emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl]),
CurrMod = get(currmod),
{InternalFunc,NewNthObj}=
case ObjName of
{no_mod,no_name} ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],NthObj};
- {ModuleName,Name} ->
- emit_ext_fun(enc,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(_,ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,_} =
- case ObjName of
- {no_mod,no_name} ->
gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
{CurrMod,Name} ->
emit({" fun 'enc_",Name,"'/3"}),
{[],NthObj};
{ModuleName,Name} ->
emit_ext_fun(enc,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'enc_",Name,"'}"]),
{[],NthObj};
_ ->
emit({" fun 'enc_",ObjName,"'/3"}),
{[],NthObj}
end,
- emit([";",nl]),
- emit_default_getenc(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- InternalFunc ++ Acc;
+ emit({";",nl}),
+ gen_objset_enc(Erules, ObjSetName, UniqueName, T, ClName, ClFields,
+ NewNthObj, InternalFunc ++ Acc);
%% See X.681 Annex E for the following case
gen_objset_enc(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj,Acc) ->
@@ -1167,7 +1103,9 @@ gen_objset_enc(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
emit({indent(6),"{Val,Len}",nl}),
emit({indent(3),"end.",nl,nl}),
Acc;
-gen_objset_enc(_,_,_,[],_,_,_,Acc) ->
+gen_objset_enc(_, ObjSetName, UniqueName, [], _, _, _, Acc) ->
+ emit_default_getenc(ObjSetName, UniqueName),
+ emit({".",nl,nl}),
Acc.
emit_ext_fun(EncDec,ModuleName,Name) ->
@@ -1181,78 +1119,34 @@ emit_default_getenc(ObjSetName,UniqueName) ->
%% 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(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- if
- M == CurrMod ->
- emit([indent(12),"'enc_",T,"'(Val)"]);
- true ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
-%% Tag = [encode_tag_val((decode_class(X#tag.class) bsl 10) +
-%% X#tag.number) ||
-%% X <- OTag],
- Tag = [encode_tag_val(decode_class(X#tag.class),
- X#tag.form,X#tag.number) ||
- X <- OTag],
- emit([indent(12),"'",M,"':'enc_",T,"'(Val, ",{asis,Tag},")"])
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,[]);
- false ->
- %% This field was not present in the object thus there
- %% were no type in the table and we therefore generate
- %% code that returns the input for application treatment.
- emit([indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Val of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Val)",nl,
- indent(12),"end,",nl,
- indent(12),"{Val,Len}"]),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,[])
- end;
+gen_inlined_enc_funs(Fields, [{typefield,_,_}|_]=T, ObjSetName, NthObj) ->
+ emit([indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl]),
+ gen_inlined_enc_funs1(Fields, T, ObjSetName, [], NthObj, []);
gen_inlined_enc_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
gen_inlined_enc_funs(_,[],_,NthObj) ->
{[],NthObj}.
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
+gen_inlined_enc_funs1(Fields, [{typefield,Name,_}|Rest], ObjSetName,
+ Sep0, NthObj, Acc0) ->
+ emit(Sep0),
+ Sep = [";",nl],
CurrMod = get(currmod),
InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ {Acc,NAdd} =
+ case lists:keyfind(Name,1,Fields) of
+ {_,#type{}=Type} ->
+ {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc0,N};
+ {_,#typedef{}=Type} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
+ {Ret,N} = emit_inner_of_fun(Type, InternalDefFunName),
+ {Ret++Acc0,N};
+ {_,#'Externaltypereference'{module=M,type=T}} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
if
- M == CurrMod ->
+ M =:= CurrMod ->
emit([indent(12),"'enc_",T,"'(Val)"]);
true ->
#typedef{typespec=Type} = asn1_db:dbget(M,T),
@@ -1260,27 +1154,30 @@ gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
Tag = [encode_tag_val(decode_class(X#tag.class),
X#tag.form,X#tag.number) ||
X <- OTag],
- emit([indent(12),"'",M,"':'enc_",T,"'(Val, ",{asis,Tag},")"])
+ emit([indent(12),"'",M,"':'enc_",T,"'(Val, ",
+ {asis,Tag},")"])
end,
- {Acc,0};
+ {Acc0,0};
false ->
%% This field was not present in the object thus there
%% were no type in the table and we therefore generate
%% code that returns the input for application
%% treatment.
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"Len = case Val of",nl,
- indent(15),"Bin when is_binary(Bin) -> byte_size(Bin);",nl,
- indent(15),"_ -> length(Val)",nl,indent(12),"end,",nl,
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12),"Len = case Val of",nl,
+ indent(15),"Bin when is_binary(Bin) -> "
+ "byte_size(Bin);",nl,
+ indent(15),"_ -> length(Val)",nl,
+ indent(12),"end,",nl,
indent(12),"{Val,Len}"]),
- {Acc,0}
+ {Acc0,0}
end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
+ gen_inlined_enc_funs1(Fields, Rest, ObjSetName, Sep, NthObj+NAdd, Acc);
+gen_inlined_enc_funs1(Fields,[_|Rest], ObjSetName, Sep, NthObj, Acc)->
+ gen_inlined_enc_funs1(Fields, Rest, 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(TDef=#typedef{name={ExtMod,Name},typespec=Type},
@@ -1319,10 +1216,6 @@ emit_inner_of_fun(Type,_) when is_record(Type,type) ->
X#tag.form,X#tag.number)||X <- OTag],
emit([indent(9),Def," ->",nl,indent(12)]),
gen_encode_prim(ber,Type,{asis,lists:reverse(Tag)},"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val)"]);
#'Externaltypereference'{module=CurrMod,type=T} ->
emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
"'(Val)"]);
@@ -1345,8 +1238,8 @@ 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(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj)->
+gen_objset_dec(Erules, ObjSName, UniqueName, [{ObjName,Val,Fields}|T],
+ ClName, ClFields, NthObj)->
emit(["'getdec_",ObjSName,"'(",{asis,UniqueName},",",
{asis,Val},") ->",nl]),
CurrMod = get(currmod),
@@ -1359,35 +1252,14 @@ gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
NthObj;
{ModuleName,Name} ->
emit_ext_fun(dec,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'dec_",Name,"'}"]),
NthObj;
_ ->
emit([" fun 'dec_",ObjName,"'/3"]),
NthObj
end,
emit([";",nl]),
- gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,
- ClFields,NewNthObj);
-gen_objset_dec(_,ObjSetName,UniqueName,[{ObjName,Val,Fields}],
- _ClName,ClFields,NthObj) ->
- emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl]),
- CurrMod = get(currmod),
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/3"]);
- {ModuleName,Name} ->
- emit_ext_fun(dec,ModuleName,Name);
-% emit([" {'",ModuleName,"', 'dec_",Name,"'}"]);
- _ ->
- emit([" fun 'dec_",ObjName,"'/3"])
- end,
- emit([";",nl]),
- emit_default_getdec(ObjSetName,UniqueName),
- emit([".",nl,nl]),
- ok;
+ gen_objset_dec(Erules, ObjSName, UniqueName, T, ClName,
+ ClFields, NewNthObj);
gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj) ->
emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
@@ -1401,86 +1273,41 @@ gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
indent(4),"end",nl]),
emit([indent(2),"end.",nl,nl]),
ok;
-gen_objset_dec(_,_,_,[],_,_,_) ->
+gen_objset_dec(_, ObjSetName, UniqueName, [], _, _, _) ->
+ emit_default_getdec(ObjSetName, UniqueName),
+ emit([".",nl,nl]),
ok.
emit_default_getdec(ObjSetName,UniqueName) ->
emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", 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(Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- CurrMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- if
- M == CurrMod ->
- emit([indent(12),"'dec_",T,"'(Bytes)"]);
- true ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number ||
- X <- OTag],
- emit([indent(12),"'",M,"':'dec_",T,"'(Bytes, ",{asis,Tag},")"])
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
- false ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Bytes of",nl,
- indent(15),"B when is_binary(B) -> byte_size(B);",nl,
- indent(15),"_ -> length(Bytes)",nl,
- indent(12),"end,",nl,
- indent(12),"{Bytes,[],Len}"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
- NthObj.
+gen_inlined_dec_funs(Fields, ClFields, ObjSetName, NthObj) ->
+ emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl]),
+ gen_inlined_dec_funs1(Fields, ClFields, ObjSetName, "", NthObj).
-gen_inlined_dec_funs1(Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
+gen_inlined_dec_funs1(Fields, [{typefield,Name,Prop}|Rest],
+ ObjSetName, Sep0, NthObj) ->
+ emit(Sep0),
+ Sep = [";",nl],
DecProp = case Prop of
'OPTIONAL' -> opt_or_default;
{'DEFAULT',_} -> opt_or_default;
_ -> mandatory
end,
- CurrMod = get(currmod),
InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit([";",nl]),
+ N = case lists:keyfind(Name, 1, Fields) of
+ {_,#type{}=Type} ->
emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
+ {_,#typedef{}=Type} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
+ {_,#'Externaltypereference'{module=M,type=T}} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
+ CurrMod = get(currmod),
if
- M == CurrMod ->
+ M =:= CurrMod ->
emit([indent(12),"'dec_",T,"'(Bytes)"]);
true ->
#typedef{typespec=Type} = asn1_db:dbget(M,T),
@@ -1491,21 +1318,20 @@ gen_inlined_dec_funs1(Fields,[{typefield,Name,Prop}|Rest],
end,
0;
false ->
- emit([";",nl,
- indent(9),{asis,Name}," ->",nl,
+ emit([indent(9),{asis,Name}," ->",nl,
indent(12),"Len = case Bytes of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
+ indent(15),"B when is_binary(B) -> byte_size(B);",nl,
indent(15),"_ -> length(Bytes)",nl,
indent(12),"end,",nl,
indent(12),"{Bytes,[],Len}"]),
0
end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit([nl,indent(6),"end",nl]),
- emit([indent(3),"end"]),
+ gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj+N);
+gen_inlined_dec_funs1(Fields, [_|Rest], ObjSetName, Sep, NthObj)->
+ gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj);
+gen_inlined_dec_funs1(_, [], _, _, NthObj) ->
+ emit([nl,indent(6),"end",nl,
+ indent(3),"end"]),
NthObj.
emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
@@ -1561,10 +1387,9 @@ emit_inner_of_decfun(Type,Prop,_) when is_record(Type,type) ->
gen_internal_funcs(_,[]) ->
ok;
gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,
-% "'(Tlv, OptOrMand, TagIn) ->",nl]),
- "'(Tlv, TagIn) ->",nl]),
+ gen_encode_user(Erules, TypeDef, false),
+ emit([nl,nl,
+ "'dec_",TypeDef#typedef.name,"'(Tlv, TagIn) ->",nl]),
gen_decode_user(Erules,TypeDef),
gen_internal_funcs(Erules,Rest).
@@ -1615,46 +1440,23 @@ decode_type('BMPString') -> 30;
decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-add_removed_bytes() ->
- asn1ct_name:delete(rb),
- add_removed_bytes(asn1ct_name:all(rb)).
-
-add_removed_bytes([H,T1|T]) ->
- emit({{var,H},"+"}),
- add_removed_bytes([T1|T]);
-add_removed_bytes([H|T]) ->
- emit({{var,H}}),
- add_removed_bytes(T);
-add_removed_bytes([]) ->
- true.
-
-mkfuncname(WhatKind,DecOrEnc) ->
- case WhatKind of
- #'Externaltypereference'{module=Mod,type=EType} ->
- CurrMod = get(currmod),
- case CurrMod of
- Mod ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- _ ->
-% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
- lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
- end;
- #'typereference'{val=EType} ->
+mkfuncname(#'Externaltypereference'{module=Mod,type=EType}, DecOrEnc) ->
+ CurrMod = get(currmod),
+ case CurrMod of
+ Mod ->
lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
-
+ _ ->
+ lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
end.
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
+get_size_constraint(C) ->
+ case lists:keyfind('SizeConstraint', 1, C) of
+ false -> [];
+ {_,{_,[]}} -> []; %Extensible.
+ {_,{Sv,Sv}} -> Sv;
+ {_,{_,_}=Tc} -> Tc
end.
-
get_class_fields(#classdef{typespec=ObjClass}) ->
ObjClass#objectclass.fields;
get_class_fields(#objectclass{fields=Fields}) ->