1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
16
%% $Id: asn1ct_constructed_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
18
-module(asn1ct_constructed_ber_bin_v2).
20
-export([gen_encode_sequence/3]).
21
-export([gen_decode_sequence/3]).
22
-export([gen_encode_set/3]).
23
-export([gen_decode_set/3]).
24
-export([gen_encode_sof/4]).
25
-export([gen_decode_sof/4]).
26
-export([gen_encode_choice/3]).
27
-export([gen_decode_choice/3]).
30
-include("asn1_records.hrl").
32
-import(asn1ct_gen, [emit/1,demit/1]).
33
-import(asn1ct_constructed_ber,[match_tag/2]).
35
-define(ASN1CT_GEN_BER,asn1ct_gen_ber_bin_v2).
37
% the encoding of class of tag bits 8 and 7
38
-define(UNIVERSAL, 0).
39
-define(APPLICATION, 16#40).
40
-define(CONTEXT, 16#80).
41
-define(PRIVATE, 16#C0).
43
% primitive or constructed encoding % bit 6
44
-define(PRIMITIVE, 0).
45
-define(CONSTRUCTED, 2#00100000).
50
%%===============================================================================
51
%%===============================================================================
52
%%===============================================================================
53
%% Encode/decode SEQUENCE (and SET)
54
%%===============================================================================
55
%%===============================================================================
56
%%===============================================================================
58
gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
60
asn1ct_name:new(term),
61
asn1ct_name:new(bytes),
63
%% if EXTERNAL type the input value must be transformed to
69
"NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
76
{SeqOrSet,TableConsInfo,CompList} =
78
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
80
#'SET'{tablecinf=TCI,components=CL} ->
83
Ext = extensible(CompList),
84
CompList1 = case CompList of
89
%% don't match recordname for now, because of compatibility reasons
90
%% emit(["{'",asn1ct_gen:list2rname(Typename),"'"]),
92
case length(CompList1) of
97
mkcindexlist([Tc || Tc <- lists:seq(1,CompListLen)])
99
emit(["} = ",ValName,",",nl]),
101
case TableConsInfo of
102
#simpletableattributes{usedclassfield=Used,
103
uniqueclassfield=Unique} when Used /= Unique ->
105
%% ObjectSet, name of the object set in constraints
107
#simpletableattributes{objectsetname=ObjectSet,
110
usedclassfield=UniqueFieldName,
111
uniqueclassfield=UniqueFieldName,
112
valueindex=ValueIndex} -> %% N is index of attribute that determines constraint
116
asn1_db:dbget(Module,OSName);
118
asn1_db:dbget(get(currmod),OSName)
120
% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
121
% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
122
case (OSDef#typedef.typespec)#'ObjectSet'.gen of
125
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
127
emit([ObjectEncode," = ",nl]),
128
emit([" 'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
130
ValueMatch = value_match(ValueIndex,
131
lists:concat(["Cindex",N])),
132
emit([indent(35),ValueMatch,"),",nl]),
133
{AttrN,ObjectEncode};
138
case D#type.tablecinf of
140
%% when the simpletableattributes was at an outer
141
%% level and the objfun has been passed through the
143
{"got objfun through args","ObjFun"};
149
gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
151
emit([nl," BytesSoFar = "]),
153
'SET' when (D#type.def)#'SET'.sorted == dynamic ->
154
emit("?RT_BER:dynamicsort_SET_components(["),
155
mkvlist(asn1ct_name:all(encBytes)),
159
mkvlist(asn1ct_name:all(encBytes)),
163
case asn1ct_name:all(encLen) of
169
emit(["?RT_BER:encode_tags(TagIn, BytesSoFar, LenSoFar)."
172
gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
174
asn1ct_name:new(tag),
175
#'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
176
Ext = extensible(CList),
177
CompList = case CList of
182
emit([" %%-------------------------------------------------",nl]),
183
emit([" %% decode tag and length ",nl]),
184
emit([" %%-------------------------------------------------",nl]),
186
asn1ct_name:new(tlv),
188
EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
191
emit([{curr,tlv}," = "])
193
emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
194
asn1ct_name:new(tlv),
197
{DecObjInf,UniqueFName,ValueIndex} =
198
case TableConsInfo of
199
#simpletableattributes{objectsetname=ObjectSet,
201
usedclassfield=UniqueFieldName,
202
uniqueclassfield=UniqueFieldName,
203
valueindex=ValIndex} ->
204
% {ObjectSet,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
205
F = fun(#'ComponentType'{typespec=CT})->
206
case {CT#type.constraint,CT#type.tablecinf} of
207
{[],[{objfun,_}|_]} -> true;
211
case lists:any(F,CompList) of
212
true -> % when component relation constraint establish
213
%% relation from a component to another components
215
{{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
216
UniqueFieldName,ValIndex};
218
{{AttrN,ObjectSet},UniqueFieldName,ValIndex}
221
% case D#type.tablecinf of
223
% {{"got objfun through args","ObjFun"},false,false};
228
case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
229
no_terms -> % an empty sequence
231
demit(["Result = "]), %dbg
232
%% return value as record
234
emit([" {'",asn1ct_gen:list2rname(Typename),"'}.",nl,nl]);
235
{LeadingAttrTerm,PostponedDecArgs} ->
237
case {LeadingAttrTerm,PostponedDecArgs} of
242
{[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
243
DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
244
ValueMatch = value_match(ValueIndex,Term),
245
emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
246
{asis,UniqueFName},", ",ValueMatch,"),",nl]),
247
gen_dec_postponed_decs(DecObj,PostponedDecArgs)
249
demit(["Result = "]), %dbg
250
%% return value as record
253
emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
255
emit(["case ",{prev,tlv}," of",nl,
257
"_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
258
"}}}) % extra fields not allowed",nl,
264
emit([" OldFormat={'",asn1ct_gen:list2rname(Typename),
266
mkvlist(asn1ct_name:all(term)),
268
emit([" asn1rt_check:transform_to_EXTERNAL1994",
271
emit([" {'",asn1ct_gen:list2rname(Typename),"', "]),
272
mkvlist(asn1ct_name:all(term)),
277
gen_dec_postponed_decs(_,[]) ->
279
gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,
280
TmpTerm,_Tag,OptOrMand}|Rest]) ->
282
asn1ct_name:new(tmpterm),
283
asn1ct_name:new(reason),
284
asn1ct_name:new(tmptlv),
286
emit([Term," = ",nl]),
287
N = case OptOrMand of
290
emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
293
emit_opt_or_mand_check(Val,TmpTerm),
296
emit([indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
297
", ",TmpTerm,", ",{asis,PFNList},")) of",nl]),
298
emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
299
emit([indent(N+9),"exit({'Type not compatible with table constraint',",
300
{curr,reason},"});",nl]),
301
emit([indent(N+6),{curr,tmpterm}," ->",nl]),
302
emit([indent(N+9),{curr,tmpterm},nl]),
305
mandatory -> emit([indent(N+3),"end,",nl]);
307
emit([indent(N+3),"end",nl,
308
indent(3),"end,",nl])
310
gen_dec_postponed_decs(DecObj,Rest).
312
emit_opt_or_mand_check(Value,TmpTerm) ->
313
emit([indent(3),"case ",TmpTerm," of",nl,
314
indent(6),{asis,Value}," ->",{asis,Value},";",nl,
315
indent(6),"_ ->",nl]).
317
%%============================================================================
320
%%============================================================================
322
gen_encode_set(Erules,Typename,D) when record(D,type) ->
323
gen_encode_sequence(Erules,Typename,D).
325
gen_decode_set(Erules,Typename,D) when record(D,type) ->
327
asn1ct_name:new(term),
328
asn1ct_name:new(tag),
329
#'SET'{tablecinf=TableConsInfo,components=TCompList} = D#type.def,
330
Ext = extensible(TCompList),
331
CompList = case TCompList of
337
asn1ct_name:new(tlv),
339
EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
342
emit([{curr,tlv}," = "])
344
emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
348
{DecObjInf,UniqueFName} =
349
case TableConsInfo of
350
{ObjectSet,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
351
F = fun(#'ComponentType'{typespec=CT})->
352
case {CT#type.constraint,CT#type.tablecinf} of
353
{[],[{objfun,_}|_]} -> true;
357
case lists:any(F,CompList) of
358
true -> % when component relation constraint establish
359
%% relation from a component to another components
361
{{AttrN,{deep,ObjectSet,UniqueFieldName}},
364
{{AttrN,ObjectSet},UniqueFieldName}
374
emit(["SetFun = fun(FunTlv) ->", nl]),
375
emit(["case FunTlv of ",nl]),
376
NextNum = gen_dec_set_cases(Erules,Typename,CompList,1),
377
emit([indent(6), {curr,else}," -> ",nl,
378
indent(9),"{",NextNum,", ",{curr,else},"}",nl]),
379
emit([indent(3),"end",nl]),
380
emit([indent(3),"end,",nl]),
382
emit(["PositionList = [SetFun(TempTlv)|| TempTlv <- ",{curr,tlv},"],",nl]),
383
asn1ct_name:new(tlv),
384
emit([{curr,tlv}," = [Stlv || {_,Stlv} <- lists:sort(PositionList)],",nl]),
388
case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
389
no_terms -> % an empty sequence
391
demit(["Result = "]), %dbg
392
%% return value as record
393
emit([" {'",asn1ct_gen:list2rname(Typename),"'}.",nl]);
394
{LeadingAttrTerm,PostponedDecArgs} ->
396
case {LeadingAttrTerm,PostponedDecArgs} of
401
{[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
402
DecObj = lists:concat(['DecObj',LeadingAttr,Term]),
403
emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
404
{asis,UniqueFName},", ",Term,"),",nl]),
405
gen_dec_postponed_decs(DecObj,PostponedDecArgs)
407
demit(["Result = "]), %dbg
408
%% return value as record
411
emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
413
emit(["case ",{prev,tlv}," of",nl,
415
"_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
416
"}}}) % extra fields not allowed",nl,
419
emit([" {'",asn1ct_gen:list2rname(Typename),"', "]),
420
mkvlist(asn1ct_name:all(term)),
425
%%===============================================================================
426
%%===============================================================================
427
%%===============================================================================
428
%% Encode/decode SEQUENCE OF and SET OF
429
%%===============================================================================
430
%%===============================================================================
431
%%===============================================================================
433
gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
435
{SeqOrSetOf, Cont} = D#type.def,
437
Objfun = case D#type.tablecinf of
444
emit([" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
445
"_components'(Val",Objfun,",[],0),",nl]),
447
emit([" ?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl,nl]),
449
gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
452
gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when record(D,type) ->
454
{SeqOrSetOf, _TypeTag, Cont} =
456
{'SET OF',_Cont} -> {'SET OF','SET',_Cont};
457
{'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
459
TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
461
emit([" %%-------------------------------------------------",nl]),
462
emit([" %% decode tag and length ",nl]),
463
emit([" %%-------------------------------------------------",nl]),
465
asn1ct_name:new(tlv),
467
" = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
472
InnerType = asn1ct_gen:get_inner(Cont#type.def),
473
ContName = case asn1ct_gen:type(InnerType) of
474
Atom when atom(Atom) -> Atom;
479
case D#type.tablecinf of
485
gen_dec_line(Erules,TypeName,ContName,[],Cont,mandatory,ObjFun),
486
%% gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
487
emit([" || ",{curr,v}," <- ",{curr,tlv},"].",nl,nl,nl]).
490
gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
491
when record(Cont,type)->
493
{Objfun,Objfun_novar,EncObj} =
494
case Cont#type.tablecinf of
496
{", ObjFun",", _",{no_attr,"ObjFun"}};
500
emit(["'enc_",asn1ct_gen:list2name(Typename),
501
"_components'([]",Objfun_novar,", AccBytes, AccLen) -> ",nl]),
503
case catch lists:member(der,get(encoding_options)) of
506
"{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
508
emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
510
emit(["'enc_",asn1ct_gen:list2name(Typename),
511
"_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
512
TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
513
gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
514
mandatory,"{EncBytes,EncLen} = ",EncObj),
516
emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
517
"_components'(T",Objfun,","]),
518
emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
520
%%============================================================================
521
%% Encode/decode CHOICE
523
%%============================================================================
525
gen_encode_choice(Erules,Typename,D) when record(D,type) ->
526
ChoiceTag = D#type.tag,
527
{'CHOICE',CompList} = D#type.def,
528
Ext = extensible(CompList),
529
CompList1 = case CompList of
533
gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
536
gen_decode_choice(Erules,Typename,D) when record(D,type) ->
538
asn1ct_name:new(bytes),
539
ChoiceTag = D#type.tag,
540
{'CHOICE',CompList} = D#type.def,
541
Ext = extensible(CompList),
542
CompList1 = case CompList of
546
gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
550
%%============================================================================
553
%%============================================================================
555
gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],Pos,Ext,EncObj) ->
556
asn1ct_name:new(encBytes),
557
asn1ct_name:new(encLen),
561
io_lib:format("Cindex~w",[Pos]);
563
io_lib:format("Cindex~w",[Pos])
565
InnerType = asn1ct_gen:get_inner(Type#type.def),
566
print_attribute_comment(InnerType,Pos,Cname,Prop),
567
gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
569
gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj);
571
gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
574
%%============================================================================
577
%%============================================================================
579
gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
580
gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
583
gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
585
gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
589
{LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
592
asn1ct_name:new(bytes),
593
gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
594
LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
597
gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
601
%%----------------------------
603
%%----------------------------
605
gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
607
case Type#type.def of
608
#'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
609
_ -> asn1ct_gen:get_inner(Type#type.def)
611
% case asn1ct_gen:get_constraint(Type#type.constraint,
612
% tableconstraint_info) of
614
% asn1ct_gen:get_inner(Type#type.def);
618
Prop1 = case {Prop,Ext} of
619
{mandatory,{ext,Epos,_}} when Pos >= Epos ->
624
print_attribute_comment(InnerType,Pos,Cname,Prop1),
625
asn1ct_name:new(term),
626
emit_term_tlv(Prop1,InnerType,DecObjInf),
629
gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
631
asn1ct_name:new(tlv),
632
asn1ct_name:new(form),
636
emit_term_tlv({'DEFAULT',_},InnerType,DecObjInf) ->
637
emit_term_tlv(opt_or_def,InnerType,DecObjInf);
638
emit_term_tlv('OPTIONAL',InnerType,DecObjInf) ->
639
emit_term_tlv(opt_or_def,InnerType,DecObjInf);
640
emit_term_tlv(Prop,{typefield,_},DecObjInf) ->
641
emit_term_tlv(Prop,type_or_object_field,DecObjInf);
642
emit_term_tlv(Prop,{objectfield,_,_},DecObjInf) ->
643
emit_term_tlv(Prop,type_or_object_field,DecObjInf);
644
emit_term_tlv(opt_or_def,type_or_object_field,_) ->
645
asn1ct_name:new(tmpterm),
646
emit(["{",{curr,tmpterm},",",{curr,tlv},"} = "]);
647
emit_term_tlv(opt_or_def,_,_) ->
648
emit(["{",{curr,term},",",{curr,tlv},"} = "]);
649
emit_term_tlv(_,type_or_object_field,false) ->
650
emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
652
emit_term_tlv(_,type_or_object_field,_) ->
653
asn1ct_name:new(tmpterm),
654
emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl]),
655
emit([nl," ",{curr,tmpterm}," = "]);
656
emit_term_tlv(mandatory,_,_) ->
657
emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
661
gen_dec_set_cases(_Erules,_TopType,[],Pos) ->
663
gen_dec_set_cases(Erules,TopType,[Comp|RestComps],Pos) ->
664
Name = Comp#'ComponentType'.name,
665
Type = Comp#'ComponentType'.typespec,
666
CTags = Comp#'ComponentType'.tags,
668
emit([indent(6),"%",Name,nl]),
669
Tags = case Type#type.tag of
670
[] -> % this is a choice without explicit tag
671
[(?ASN1CT_GEN_BER:decode_class(T1class) bsl 10) + T1number||
672
{T1class,T1number} <- CTags];
674
[(?ASN1CT_GEN_BER:decode_class(FirstTag#tag.class) bsl 10) + FirstTag#tag.number]
676
% emit([indent(6),"%Tags: ",Tags,nl]),
677
% emit([indent(6),"%Type#type.tag: ",Type#type.tag,nl]),
678
CaseFun = fun(TagList=[H|T],Fun,N) ->
679
Semicolon = case TagList of
680
[_Tag1,_|_] -> [";",nl];
683
emit(["TTlv = {",H,",_} ->",nl]),
684
emit([indent(4),"{",Pos,", TTlv}",Semicolon]),
691
CaseFun(Tags,CaseFun,0),
693
gen_dec_set_cases(Erules,TopType,RestComps,Pos+1).
697
%%---------------------------------------------
699
%%---------------------------------------------
700
%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
703
gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
704
gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
706
gen_enc_choice1(Erules,TopType,_Tag,CompList,_Ext) ->
708
emit([" {EncBytes,EncLen} = case element(1,Val) of",nl]),
709
gen_enc_choice2(Erules,TopType,CompList),
710
emit([nl," end,",nl,nl]),
712
emit(["?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl]).
715
gen_enc_choice2(Erules,TopType,[H1|T]) when record(H1,'ComponentType') ->
716
Cname = H1#'ComponentType'.name,
717
Type = H1#'ComponentType'.typespec,
718
emit([" ",{asis,Cname}," ->",nl]),
720
case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
721
componentrelation)} of
722
{#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
723
asn1ct_name:new(tmpBytes),
724
asn1ct_name:new(encBytes),
725
asn1ct_name:new(encLen),
726
Emit = ["{",{curr,tmpBytes},", _} = "],
727
{{no_attr,"ObjFun"},Emit};
731
% case asn1ct_gen:get_constraint(Type#type.constraint,
732
% tableconstraint_info) of
736
% asn1ct_name:new(tmpBytes),
737
% asn1ct_name:new(encBytes),
738
% asn1ct_name:new(encLen),
739
% Emit = ["{",{curr,tmpBytes},", _} = "],
740
% {{no_attr,"ObjFun"},Emit}
742
gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
743
mandatory,Assign,Encobj),
747
emit([",",nl,indent(9),"{",{curr,encBytes},", ",
753
emit([indent(6), "Else -> ",nl,
754
indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
758
gen_enc_choice2(Erules,TopType,T);
760
gen_enc_choice2(_Erules,_TopType,[]) ->
766
%%--------------------------------------------
768
%%--------------------------------------------
770
gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
772
asn1ct_name:new(tlv),
774
" = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
775
asn1ct_name:new(tlv),
777
emit(["case (case ",{prev,tlv},
778
" of [Ctemp",{prev,tlv},"] -> Ctemp",{prev,tlv},
779
"; _ -> ",{prev,tlv}," end)"," of",nl]),
780
asn1ct_name:new(tagList),
781
asn1ct_name:new(choTags),
782
asn1ct_name:new(res),
783
gen_dec_choice_cases(Erules,TopType,CompList),
784
emit([indent(6), {curr,else}," -> ",nl]),
787
emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
788
{curr,else},"}}})",nl]);
790
emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},")}",nl])
792
emit([indent(3),"end",nl]),
793
asn1ct_name:new(tag),
794
asn1ct_name:new(else).
797
gen_dec_choice_cases(_Erules,_TopType, []) ->
799
gen_dec_choice_cases(Erules,TopType, [H|T]) ->
800
Cname = H#'ComponentType'.name,
801
Type = H#'ComponentType'.typespec,
802
Prop = H#'ComponentType'.prop,
803
Tags = Type#type.tag,
804
Fcases = fun([{T1class,T1number}|Tail],Fun) ->
805
emit([indent(4),{curr,v}," = {",
806
(?ASN1CT_GEN_BER:decode_class(T1class) bsl 10) +
807
T1number,",_} -> ",nl]),
808
emit([indent(8),"{",{asis,Cname},", "]),
809
gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
815
emit([nl,"%% '",Cname,"'",nl]),
816
case {Tags,asn1ct:get_gen_state_field(namelist)} of
817
{[],_} -> % choice without explicit tags
818
Fcases(H#'ComponentType'.tags,Fcases);
819
{[FirstT|_RestT],[{Cname,undecoded}|Names]} ->
820
DecTag=(?ASN1CT_GEN_BER:decode_class(FirstT#tag.class) bsl 10) +
822
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
824
asn1ct:update_gen_state(namelist,Names),
825
emit([indent(4),{curr,res}," = ",
826
match_tag(ber_bin,{FirstT#tag.class,FirstT#tag.number}),
828
emit([indent(8),"{",{asis,Cname},", {'",
829
asn1ct_gen:list2name([Cname|TopType]),"',",
830
{curr,res},"}};",nl,nl]);
831
{[FirstT|RestT],_} ->
833
(?ASN1CT_GEN_BER:decode_class(FirstT#tag.class) bsl 10) +
834
FirstT#tag.number,", ",{curr,v},"} -> ",nl]),
835
emit([indent(8),"{",{asis,Cname},", "]),
836
gen_dec_line(Erules,TopType,Cname,[],Type#type{tag=RestT},Prop,false),
839
gen_dec_choice_cases(Erules,TopType, T).
843
%%---------------------------------------
844
%% Generate the encode/decode code
845
%%---------------------------------------
847
gen_enc_line(Erules,TopType,Cname,
848
Type=#type{constraint=[{componentrelation,_,_}],
849
def=#'ObjectClassFieldType'{type={typefield,_}}},
850
Element,Indent,OptOrMand=mandatory,EncObj)
851
when list(Element) ->
852
asn1ct_name:new(tmpBytes),
853
gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
854
["{",{curr,tmpBytes},",_} = "],EncObj);
855
gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
856
when list(Element) ->
857
gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
858
["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
860
gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
861
when list(Element) ->
862
IndDeep = indent(Indent),
863
Tag = lists:reverse([?ASN1CT_GEN_BER:encode_tag_val(
864
?ASN1CT_GEN_BER:decode_class(X#tag.class),
867
|| X <- Type#type.tag]),
868
InnerType = asn1ct_gen:get_inner(Type#type.def),
869
WhatKind = asn1ct_gen:type(InnerType),
872
gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
874
case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
875
componentrelation)} of
876
% #type{constraint=[{tableconstraint_info,RefedFieldName}],
877
% def={typefield,_}} ->
878
{#type{def=#'ObjectClassFieldType'{type={typefield,_},
879
fieldname=RefedFieldName}},
880
{componentrelation,_,_}} ->
881
{_LeadingAttrName,Fun} = EncObj,
882
case RefedFieldName of
884
throw({error,{notype,type_from_object,T}});
885
{Name,RestFieldNames} when atom(Name) ->
889
% emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
890
emit(["{",{curr,tmpBytes},",_ } = "])
893
emit([Fun,"(",{asis,Name},", ",Element,", ",
894
{asis,RestFieldNames},"),",nl]),
898
emit(["{",{curr,encBytes},",",{curr,encLen},
900
emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
901
",",{asis,Tag},")"]);
903
% emit(["{",{next,tmpBytes},", _} = "]),
904
emit(["{",{next,tmpBytes},",",{curr,tmpLen},
906
emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
907
",",{asis,Tag},"),",nl]),
909
emit(["{",{next,tmpBytes},", ",{curr,tmpLen},"}"])
912
throw({asn1,{'internal error'}})
914
{{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
916
{componentrelation,_,_}} ->
917
%% this is when the dotted list in the FieldName has more
919
{_LeadingAttrName,Fun} = EncObj,
920
emit(["?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
921
", ",Element,", ",{asis,PFNList},"))"]);
926
case Type#type.def of
927
#'ObjectClassFieldType'{type={fixedtypevaluefield,_,Btype}} ->
932
?ASN1CT_GEN_BER:gen_encode_prim(ber,EncType,{asis,Tag},
935
emit(["'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"]);
937
case Type#type.def of
938
#'ObjectClassFieldType'{} -> %Open Type
939
?ASN1CT_GEN_BER:gen_encode_prim(ber,#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
941
?ASN1CT_GEN_BER:gen_encode_prim(ber,Type,
946
{EncFunName, _EncMod, _EncFun} =
947
mkfuncname(TopType,Cname,WhatKind,"enc_"),
948
case {WhatKind,Type#type.tablecinf,EncObj} of
949
{{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
950
emit([EncFunName,"(",Element,", ",{asis,Tag},
953
emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
960
emit([nl,indent(7),"end"])
963
gen_optormand_case(mandatory,_Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
966
gen_optormand_case('OPTIONAL',Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
968
emit([" case ",Element," of",nl]),
969
emit([indent(9),"asn1_NOVALUE -> {",
970
empty_lb(Erules),",0};",nl]),
971
emit([indent(9),"_ ->",nl,indent(12)]);
972
gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
973
InnerType,WhatKind,Element) ->
974
CurrMod = get(currmod),
975
case catch lists:member(der,get(encoding_options)) of
977
emit(" case catch "),
978
asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
979
WhatKind,{asis,DefaultValue},
982
emit([indent(12),"true -> {[],0};",nl]);
984
emit([" case ",Element," of",nl]),
985
emit([indent(9),"asn1_DEFAULT -> {",
989
#'Externalvaluereference'{module=CurrMod,
991
emit([indent(9),"?",{asis,V}," -> {",
992
empty_lb(Erules),",0};",nl]);
994
emit([indent(9),{asis,
995
DefaultValue}," -> {",
996
empty_lb(Erules),",0};",nl])
999
emit([indent(9),"_ ->",nl,indent(12)]).
1003
gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
1004
BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(v)),
1006
[(?ASN1CT_GEN_BER:decode_class(X#tag.class) bsl 10) + X#tag.number ||
1007
X <- Type#type.tag],
1009
[(?ASN1CT_GEN_BER:decode_class(Class) bsl 10) + Number||
1010
{Class,Number} <- CTags],
1012
case Type#type.def of
1013
#'ObjectClassFieldType'{type=OCFTType} ->
1016
asn1ct_gen:get_inner(Type#type.def)
1021
gen_dec_call(InnerType,Erules,TopType,Cname,Type,
1023
mandatory,", mandatory, ",DecObjInf,OptOrMand);
1024
_ -> %optional or default or a mandatory component after an extensionmark
1025
{FirstTag,RestTag} =
1032
emit(["case ",{prev,tlv}," of",nl]),
1035
[] when length(ChoiceTags) > 0 -> % a choice without explicit tag
1038
emit(["[",{curr,v}," = {",{asis,FirstTag1},
1042
emit([indent(4),"{"]),
1044
gen_dec_call(InnerType,Erules,
1049
DecObjInf,OptOrMand),
1051
emit([", Temp",{curr,tlv},"}"]),
1055
hd([Fcases(TmpTag)|| TmpTag <- FirstTag]);
1057
[] -> % an open type without explicit tag
1058
emit(["[",{curr,v},"|Temp",{curr,tlv},"] ->",nl]),
1059
emit([indent(4),"{"]),
1061
gen_dec_call(InnerType,Erules,TopType,Cname,
1062
Type,BytesVar,RestTag,mandatory,
1063
", mandatory, ",DecObjInf,
1066
emit([", Temp",{curr,tlv},"}"]),
1071
emit(["[{",{asis,FirstTag},
1072
",",{curr,v},"}|Temp",
1075
emit([indent(4),"{"]),
1077
gen_dec_call(InnerType,Erules,TopType,Cname,
1078
Type,BytesVar,RestTag,mandatory,
1079
", mandatory, ",DecObjInf,
1082
emit([", Temp",{curr,tlv},"}"]),
1087
emit([indent(4),"_ ->",nl]),
1090
emit([indent(8),"{",{asis,Def},",",{prev,tlv},"}",nl]);
1092
emit([indent(8),"{ asn1_NOVALUE, ",{prev,tlv},"}",nl])
1098
{Cname,ObjSet} -> % this must be the component were an object is
1099
%% choosen from the object set according to the table
1101
{[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
1106
gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
1107
%% this in case of a choice with typefield components
1108
asn1ct_name:new(reason),
1109
asn1ct_name:new(opendec),
1110
asn1ct_name:new(tmpterm),
1111
asn1ct_name:new(tmptlv),
1113
{FirstPFName,RestPFName} =
1114
% asn1ct_gen:get_constraint(Type#type.constraint,
1115
% tableconstraint_info),
1116
(Type#type.def)#'ObjectClassFieldType'.fieldname,
1117
emit([nl,indent(6),"begin",nl]),
1118
% emit([indent(9),{curr,opendec}," = ?RT_BER:decode_open_type(",
1119
emit([indent(9),{curr,tmptlv}," = ?RT_BER:decode_open_type(",
1120
BytesVar,",",{asis,Tag},"),",nl]),
1121
% emit([indent(9),"{",{curr,tmptlv},",_} = ?RT_BER:decode(",
1122
% {curr,opendec},"),",nl]),
1124
emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
1125
", ",{curr,tmptlv},", ",{asis,RestPFName},
1126
")) of", nl]),%% ??? What about Tag
1127
emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
1128
emit([indent(15),"exit({'Type not ",
1129
"compatible with table constraint', ",{curr,reason},"});",nl]),
1130
emit([indent(12),{curr,tmpterm}," ->",nl]),
1131
emit([indent(15),{curr,tmpterm},nl]),
1132
emit([indent(9),"end",nl,indent(6),"end",nl]),
1134
gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
1135
emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
1137
% asn1ct_gen:get_constraint(Type#type.constraint,
1138
% tableconstraint_info),
1139
(Type#type.def)#'ObjectClassFieldType'.fieldname,
1140
[{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1141
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
1142
gen_dec_call({objectfield,PrimFieldName,PFNList},_,_,Cname,_,BytesVar,Tag,_,_,_,OptOrMandComp) ->
1143
emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
1144
[{Cname,{PrimFieldName,PFNList},asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1145
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
1146
gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
1147
OptOrMand,DecObjInf,_) ->
1148
WhatKind = asn1ct_gen:type(InnerType),
1149
gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
1150
PrimOptOrMand,OptOrMand),
1152
{Cname,{_,OSet,UniqueFName,ValIndex}} ->
1153
Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1154
ValueMatch = value_match(ValIndex,Term),
1155
emit([",",nl,"ObjFun = 'getdec_",OSet,"'(",
1156
% {asis,UniqueFName},", ",{curr,term},")"]);
1157
{asis,UniqueFName},", ",ValueMatch,")"]);
1162
gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
1164
case {asn1ct:get_gen_state_field(namelist),InnerType} of
1165
{[{Cname,undecoded}|Rest],_} ->
1166
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
1168
asn1ct:update_gen_state(namelist,Rest),
1169
% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
1170
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
1172
{_,{fixedtypevaluefield,_,Btype}} ->
1173
?ASN1CT_GEN_BER:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],
1174
?PRIMITIVE,OptOrMand);
1176
?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
1177
?PRIMITIVE,OptOrMand)
1179
gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
1181
case {asn1ct:get_gen_state_field(namelist),Type#type.def} of
1182
{[{Cname,undecoded}|Rest],_} ->
1183
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
1185
asn1ct:update_gen_state(namelist,Rest),
1186
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
1188
% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
1189
{_,#'ObjectClassFieldType'{type=OpenType}} ->
1190
?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType},
1192
?PRIMITIVE,OptOrMand);
1194
?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
1195
?PRIMITIVE,OptOrMand)
1197
gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,BytesVar,
1198
Tag,_,_OptOrMand) ->
1199
case asn1ct:get_gen_state_field(namelist) of
1200
[{Cname,undecoded}|Rest] ->
1201
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
1203
asn1ct:update_gen_state(namelist,Rest),
1204
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
1207
% {DecFunName, _DecMod, _DecFun} =
1208
% case {asn1ct:get_gen_state_field(namelist),WhatKind} of
1211
case {WhatKind,Type#type.tablecinf} of
1212
{{constructed,bif},[{objfun,_}|_Rest]} ->
1213
emit([FuncName,"(",BytesVar,", ",{asis,Tag},
1216
emit([FuncName,"(",BytesVar,", ",{asis,Tag},")"])
1219
case asn1ct:get_gen_state_field(namelist) of
1220
[{Cname,List}|Rest] when list(List) ->
1222
#'Externaltypereference'{} ->
1223
%%io:format("gen_dec_call1 1:~n~p~n~n",[WhatKind]),
1224
asn1ct:add_tobe_refed_func({WhatKind,List});
1226
%%io:format("gen_dec_call1 2:~n~p~n~n",[[Cname|TopType]]),
1227
asn1ct:add_tobe_refed_func({[Cname|TopType],
1230
asn1ct:update_gen_state(namelist,Rest),
1231
Prefix=asn1ct:get_gen_state_field(prefix),
1233
mkfuncname(TopType,Cname,WhatKind,Prefix),
1234
EmitDecFunCall(DecFunName);
1235
[{Cname,parts}|Rest] ->
1236
asn1ct:update_gen_state(namelist,Rest),
1237
asn1ct:get_gen_state_field(prefix),
1238
%% This is to prepare SEQUENCE OF value in
1239
%% partial incomplete decode for a later
1240
%% part-decode, i.e. skip %% the tag.
1241
asn1ct:add_generated_refed_func({[Cname|TopType],
1244
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',"]),
1245
EmitDecFunCall("?RT_BER:match_tags"),
1249
mkfuncname(TopType,Cname,WhatKind,"dec_"),
1250
EmitDecFunCall(DecFunName)
1252
% case {WhatKind,Type#type.tablecinf} of
1253
% {{constructed,bif},[{objfun,_}|_Rest]} ->
1254
% emit([DecFunName,"(",BytesVar,", ",{asis,Tag},
1257
% emit([DecFunName,"(",BytesVar,", ",{asis,Tag},")"])
1262
%%------------------------------------------------------
1263
%% General and special help functions (not exported)
1264
%%------------------------------------------------------
1268
lists:duplicate(N,32). % 32 = space
1270
mkcindexlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
1271
emit(["Cindex",H,Sep]),
1272
mkcindexlist([T1|T], Sep);
1273
mkcindexlist([H|T], Sep) ->
1275
mkcindexlist(T, Sep);
1276
mkcindexlist([], _) ->
1280
mkcindexlist(L,", ").
1283
mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
1284
emit([{var,H},Sep]),
1285
mkvlist([T1|T], Sep);
1286
mkvlist([H|T], Sep) ->
1298
extensible(CompList) when list(CompList) ->
1300
extensible({RootList,ExtList}) ->
1301
{ext,length(RootList)+1,length(ExtList)}.
1304
print_attribute_comment(InnerType,Pos,Cname,Prop) ->
1305
CommentLine = "%%-------------------------------------------------",
1306
emit([nl,CommentLine]),
1308
{typereference,_,Name} ->
1309
emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",Name]);
1310
{'Externaltypereference',_,XModule,Name} ->
1311
emit([nl,"%% attribute ",Cname,"(",Pos,") External ",XModule,":",Name]);
1313
emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",InnerType])
1319
emit([" DEFAULT = ",{asis,Def}]);
1323
emit([nl,CommentLine,nl]).
1327
mkfuncname(TopType,Cname,WhatKind,Prefix) ->
1328
CurrMod = get(currmod),
1330
#'Externaltypereference'{module=CurrMod,type=EType} ->
1331
F = lists:concat(["'",Prefix,EType,"'"]),
1333
#'Externaltypereference'{module=Mod,type=EType} ->
1334
{lists:concat(["'",Mod,"':'",Prefix,EType,"'"]),Mod,
1335
lists:concat(["'",Prefix,EType,"'"])};
1336
{constructed,bif} ->
1337
F = lists:concat(["'",Prefix,asn1ct_gen:list2name([Cname|TopType]),"'"]),
1343
empty_lb(ber_bin) ->
1345
empty_lb(ber_bin_v2) ->
1348
value_match(Index,Value) when atom(Value) ->
1349
value_match(Index,atom_to_list(Value));
1350
value_match([],Value) ->
1352
value_match([{VI,_}|VIs],Value) ->
1353
value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
1354
value_match1(Value,[],Acc,Depth) ->
1355
Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
1356
value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
1357
value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).