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_per.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
18
-module(asn1ct_constructed_per).
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]).
29
-include("asn1_records.hrl").
30
%-compile(export_all).
32
-import(asn1ct_gen, [emit/1,demit/1]).
35
%% ENCODE GENERATOR FOR SEQUENCE TYPE ** **********
38
gen_encode_set(Erules,TypeName,D) ->
39
gen_encode_constructed(Erules,TypeName,D).
41
gen_encode_sequence(Erules,TypeName,D) ->
42
gen_encode_constructed(Erules,TypeName,D).
44
gen_encode_constructed(Erules,Typename,D) when record(D,type) ->
46
asn1ct_name:new(term),
47
asn1ct_name:new(bytes),
48
{CompList,TableConsInfo} =
50
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
52
#'SET'{tablecinf=TCI,components=CL} ->
57
emit({{var,asn1ct_name:next(val)},
58
" = asn1rt_check:transform_to_EXTERNAL1990(",
59
{var,asn1ct_name:curr(val)},"),",nl}),
64
case {Optionals = optionals(CompList),CompList} of
65
{[],EmptyCL} when EmptyCL == {[],[]};EmptyCL == [] ->
66
emit(["%%Variable setting just to eliminate ",
67
"compiler warning for unused vars!",nl,
68
"_Val = ",{var,asn1ct_name:curr(val)},",",nl]);
70
emit([{var,asn1ct_name:next(val)}," = ?RT_PER:list_to_record("]),
71
emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
72
emit([", ",{var,asn1ct_name:curr(val)},"),",nl]);
76
per -> ",Opt} = ?RT_PER:fixoptionals2(";
77
_ -> ",Opt} = ?RT_PER:fixoptionals("
79
emit({"{",{var,asn1ct_name:next(val)},Fixoptcall,
80
{asis,Optionals},",",length(Optionals),
81
",",{var,asn1ct_name:curr(val)},"),",nl})
84
Ext = extensible(CompList),
86
{ext,_,NumExt} when NumExt > 0 ->
87
emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},
88
", ",{curr,val},"),",nl]);
93
#simpletableattributes{usedclassfield=Used,
94
uniqueclassfield=Unique} when Used /= Unique ->
96
%% ObjectSet, name of the object set in constraints
98
%%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint
99
#simpletableattributes{objectsetname=ObjectSet,
102
usedclassfield=UniqueFieldName,
103
uniqueclassfield=UniqueFieldName,
104
valueindex=ValueIndex
105
} -> %% N is index of attribute that determines constraint
109
asn1_db:dbget(Module,OSName);
111
asn1_db:dbget(get(currmod),OSName)
113
case (OSDef#typedef.typespec)#'ObjectSet'.gen of
116
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
117
emit([ObjectEncode," = ",nl]),
118
emit([" 'getenc_",ObjectSet,"'(",
119
{asis,UniqueFieldName},", ",nl]),
120
El = make_element(N+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),AttrN),
121
Indent = 12 + length(atom_to_list(ObjectSet)),
124
emit([indent(Indent),El,"),",nl]);
126
emit([indent(Indent),"value_match(",
127
{asis,ValueIndex},",",El,")),",nl]),
130
{AttrN,ObjectEncode};
135
case D#type.tablecinf of
137
%% when the simpletableattributes was at an outer
138
%% level and the objfun has been passed through the
140
{"got objfun through args","ObjFun"};
148
{ext,_Pos,NumExt2} when NumExt2 > 0 ->
149
emit({"?RT_PER:setext(Extensions =/= [])"}),
152
emit({"?RT_PER:setext(false)"}),
158
case optionals(CompList) of
165
gen_enc_components_call(Typename,CompList,MaybeComma2,EncObj,Ext),
169
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170
%% generate decode function for SEQUENCE and SET
172
gen_decode_set(Erules,Typename,D) ->
173
gen_decode_constructed(Erules,Typename,D).
175
gen_decode_sequence(Erules,Typename,D) ->
176
gen_decode_constructed(Erules,Typename,D).
178
gen_decode_constructed(_Erules,Typename,D) when record(D,type) ->
180
{CompList,TableConsInfo} =
182
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
184
#'SET'{tablecinf=TCI,components=CL} ->
187
Ext = extensible(CompList),
188
MaybeComma1 = case Ext of
189
{ext,_Pos,_NumExt} ->
190
gen_dec_extension_value("Bytes"),
195
Optionals = optionals(CompList),
196
MaybeComma2 = case Optionals of
199
Bcurr = asn1ct_name:curr(bytes),
200
Bnext = asn1ct_name:next(bytes),
202
GetoptCall = "} = ?RT_PER:getoptionals2(",
203
emit({"{Opt,",{var,Bnext},GetoptCall,
204
{var,Bcurr},",",{asis,length(Optionals)},")"}),
205
asn1ct_name:new(bytes),
208
{DecObjInf,UniqueFName,ValueIndex} =
209
case TableConsInfo of
210
%% {ObjectSet,AttrN,N,UniqueFieldName} ->%% N is index of attribute that determines constraint
211
#simpletableattributes{objectsetname=ObjectSet,
213
usedclassfield=UniqueFieldName,
214
uniqueclassfield=UniqueFieldName,
215
valueindex=ValIndex} ->
216
%% {AttrN,ObjectSet};
217
F = fun(#'ComponentType'{typespec=CT})->
218
case {CT#type.constraint,CT#type.tablecinf} of
219
{[],[{objfun,_}|_R]} -> true;
223
case lists:any(F,CompList) of
224
true -> % when component relation constraint establish
225
%% relation from a component to another components
227
{{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
228
UniqueFieldName,ValIndex};
230
{{AttrN,ObjectSet},UniqueFieldName,ValIndex}
233
case D#type.tablecinf of
235
{{"got objfun through args","ObjFun"},false,false};
241
gen_dec_components_call(Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
242
case asn1ct_name:all(term) of
243
[] -> emit(MaybeComma2); % no components at all
246
case {AccTerm,AccBytes} of
251
{[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
252
DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
253
ValueMatch = value_match(ValueIndex,Term),
254
emit({DecObj," =",nl," 'getdec_",ObjSet,"'(",
255
% {asis,UniqueFName},", ",Term,"),",nl}),
256
{asis,UniqueFName},", ",ValueMatch,"),",nl}),
257
gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
259
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
260
demit({"Result = "}), %dbg
261
%% return value as record
264
emit({" OldFormat={'",asn1ct_gen:list2rname(Typename),
266
mkvlist(asn1ct_name:all(term)),
268
emit({" ASN11994Format =",nl,
269
" asn1rt_check:transform_to_EXTERNAL1994",
271
emit(" {ASN11994Format,");
273
emit(["{{'",asn1ct_gen:list2rname(Typename),"'"]),
274
mkvlist(asn1ct_name:all(term)),
277
emit({{var,asn1ct_name:curr(bytes)},"}"}),
280
gen_dec_listofopentypes(_,[],_) ->
282
gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
284
% asn1ct_name:new(term),
285
asn1ct_name:new(tmpterm),
286
asn1ct_name:new(reason),
288
emit([Term," = ",nl]),
293
emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
296
emit_opt_or_mand_check(Val,TmpTerm),
300
emit([indent(N+3),"case (catch ",DecObj,"(",
301
{asis,FirstPFN},", ",TmpTerm,", telltype,",{asis,PFNList},")) of",nl]),
302
emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
303
%% emit({indent(9),"throw({runtime_error,{","'Type not compatible with table constraint'",",",Term,"}});",nl}),
304
emit([indent(N+9),"exit({'Type not compatible with table constraint',",
305
{curr,reason},"});",nl]),
306
emit([indent(N+6),"{",{curr,tmpterm},",_} ->",nl]),
307
emit([indent(N+9),{curr,tmpterm},nl]),
311
emit([indent(N+3),"end,",nl]);
313
emit([indent(N+3),"end",nl,
314
indent(3),"end,",nl])
316
gen_dec_listofopentypes(DecObj,Rest,true).
319
emit_opt_or_mand_check(Val,Term) ->
320
emit([indent(3),"case ",Term," of",nl,
321
indent(6),{asis,Val}," ->",{asis,Val},";",nl,
322
indent(6),"_ ->",nl]).
324
%% ENCODE GENERATOR FOR THE CHOICE TYPE *******
325
%% assume Val = {Alternative,AltType}
328
%% ?RT_PER:set_choice(element(1,Val),Altnum,Altlist,ext),
329
%%case element(1,Val) of
331
%% encode_alt1(element(2,Val));
333
%% encode_alt2(element(2,Val))
337
gen_encode_choice(_Erules,Typename,D) when record(D,type) ->
338
{'CHOICE',CompList} = D#type.def,
340
Ext = extensible(CompList),
341
gen_enc_choice(Typename,CompList,Ext),
344
gen_decode_choice(_Erules,Typename,D) when record(D,type) ->
346
asn1ct_name:new(bytes),
347
{'CHOICE',CompList} = D#type.def,
348
Ext = extensible(CompList),
349
gen_dec_choice(Typename,CompList,Ext),
352
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353
% Encode generator for SEQUENCE OF type
356
gen_encode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
359
% ?RT_PER:encode_length(length(Val)),
361
{_SeqOrSetOf,ComponentType} = D#type.def,
364
case asn1ct_gen:get_constraint(D#type.constraint,
370
case D#type.tablecinf of
376
emit({nl,indent(3),"?RT_PER:encode_length(",
377
{asis,SizeConstraint},
378
",length(Val)),",nl}),
379
emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
380
"_components'(Val",ObjFun,", [])"}),
383
case ComponentType#type.def of
384
{'ENUMERATED',_,Component}->
385
ComponentType#type{def={'ENUMERATED',Component}};
388
gen_encode_sof_components(Typename,SeqOrSetOf,NewComponentType).
390
gen_decode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
393
% ?RT_PER:encode_length(length(Val)),
395
{_SeqOrSetOf,ComponentType} = D#type.def,
397
case asn1ct_gen:get_constraint(D#type.constraint,
403
case D#type.tablecinf of
409
emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",{asis,SizeConstraint},"),",nl}),
410
emit({"'dec_",asn1ct_gen:list2name(Typename),
411
"_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
413
case ComponentType#type.def of
414
{'ENUMERATED',_,Component}->
415
ComponentType#type{def={'ENUMERATED',Component}};
418
gen_decode_sof_components(Typename,SeqOrSetOf,NewComponentType).
420
gen_encode_sof_components(Typename,SeqOrSetOf,Cont) ->
421
{ObjFun,ObjFun_Var} =
422
case Cont#type.tablecinf of
428
emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([]",
429
ObjFun_Var,", Acc) -> lists:reverse(Acc);",nl,nl}),
430
emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([H|T]",
431
ObjFun,", Acc) ->",nl}),
432
emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'(T"}),
433
emit({ObjFun,", ["}),
434
%% the component encoder
435
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
438
Conttype = asn1ct_gen:get_inner(Cont#type.def),
439
Currmod = get(currmod),
440
Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
441
asn1ct_gen:rt2ct_suffix()])),
442
case asn1ct_gen:type(Conttype) of
444
gen_encode_prim_wrapper(Ctgenmod,per,Cont,false,"H");
445
% Ctgenmod:gen_encode_prim(per,Cont,false,"H");
447
NewTypename = [Constructed_Suffix|Typename],
448
emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
450
#'Externaltypereference'{module=Currmod,type=Ename} ->
451
emit({"'enc_",Ename,"'(H)",nl,nl});
452
#'Externaltypereference'{module=EMod,type=EType} ->
453
emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
455
emit({"'enc_",Conttype,"'(H)",nl,nl})
457
emit({" | Acc]).",nl}).
459
gen_decode_sof_components(Typename,SeqOrSetOf,Cont) ->
460
{ObjFun,ObjFun_Var} =
461
case Cont#type.tablecinf of
467
emit({"'dec_",asn1ct_gen:list2name(Typename),
468
"_components'(0, Bytes, _",ObjFun_Var,", Acc) ->",nl,
469
indent(3),"{lists:reverse(Acc), Bytes};",nl}),
470
emit({"'dec_",asn1ct_gen:list2name(Typename),
471
"_components'(Num, Bytes, _",ObjFun,", Acc) ->",nl}),
472
emit({indent(3),"{Term,Remain} = "}),
473
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
475
Conttype = asn1ct_gen:get_inner(Cont#type.def),
476
Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
477
asn1ct_gen:rt2ct_suffix()])),
478
case asn1ct_gen:type(Conttype) of
480
Ctgenmod:gen_dec_prim(per,Cont,"Bytes"),
483
NewTypename = [Constructed_Suffix|Typename],
484
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
485
"'(Bytes, telltype",ObjFun,"),",nl});
486
#typereference{val=Dname} ->
487
emit({"'dec_",Dname,"'(Bytes,telltype),",nl});
488
#'Externaltypereference'{module=EMod,type=EType} ->
489
emit({"'",EMod,"':'dec_",EType,"'(Bytes,telltype),",nl});
491
emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
493
emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
494
"_components'(Num-1, Remain, telltype",ObjFun,", [Term|Acc]).",nl}).
497
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498
% General and special help functions (not exported)
505
mkvlist2([H,T1|T]) ->
514
extensible(CompList) when list(CompList) ->
516
extensible({RootList,ExtList}) ->
517
{ext,length(RootList)+1,length(ExtList)}.
519
gen_dec_extension_value(_) ->
520
emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
521
asn1ct_name:new(bytes).
523
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524
%% Produce a list with positions (in the Value record) where
525
%% there are optional components, start with 2 because first element
526
%% is the record name
528
optionals({L,_Ext}) -> optionals(L,[],2);
529
optionals(L) -> optionals(L,[],2).
531
optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
532
optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
533
optionals([#'ComponentType'{prop='OPTIONAL'}|Rest],Acc,Pos) ->
534
optionals(Rest,[Pos|Acc],Pos+1);
535
optionals([#'ComponentType'{prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
536
optionals(Rest,[Pos|Acc],Pos+1);
537
optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
538
optionals(Rest,Acc,Pos+1);
539
optionals([],Acc,_) ->
543
gen_enc_components_call(TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) ->
544
%% The type has extensionmarker
545
Rpos = gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,noext),
547
{ext,_,ExtNum} when ExtNum > 0 ->
553
gen_enc_components_call1(TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext);
554
gen_enc_components_call(TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
555
%% The type has no extensionmarker
556
gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
558
gen_enc_components_call1(TopType,
559
[C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
561
MaybeComma, DynamicEnc, Ext) ->
563
put(component_type,{true,C}),
564
%% information necessary in asn1ct_gen_per_rt2ct:gen_encode_prim
568
{ext,Epos,_Enum} -> Tpos - Epos + 1
573
gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
574
{'DEFAULT',_DefVal} ->
575
gen_enc_component_default(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
578
{ext,ExtPos,_} when Tpos >= ExtPos ->
579
gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
581
gen_enc_component_mandatory(TopType,Cname,Type,Tpos,DynamicEnc,Ext)
585
erase(component_type),
592
gen_enc_components_call1(TopType,Rest,Tpos+1,"",DynamicEnc,Ext)
594
gen_enc_components_call1(_TopType,[],Pos,_,_,_) ->
597
gen_enc_component_default(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
598
% Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
599
Element = make_element(Pos+1,"Val1",Cname),
600
emit({"case ",Element," of",nl}),
602
% {ext,ExtPos,_} when Pos >= ExtPos ->
603
% emit({"asn1_NOEXTVALUE -> [];",nl});
605
emit({"asn1_DEFAULT -> [];",nl}),
607
asn1ct_name:new(tmpval),
608
emit({{curr,tmpval}," ->",nl}),
609
InnerType = asn1ct_gen:get_inner(Type#type.def),
610
emit({nl,"%% attribute number ",Pos," with type ",
612
NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
613
gen_enc_line(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
616
gen_enc_component_optional(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
617
% Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
618
Element = make_element(Pos+1,"Val1",Cname),
619
emit({"case ",Element," of",nl}),
621
% {ext,ExtPos,_} when Pos >= ExtPos ->
622
% emit({"asn1_NOEXTVALUE -> [];",nl});
624
emit({"asn1_NOVALUE -> [];",nl}),
626
asn1ct_name:new(tmpval),
627
emit({{curr,tmpval}," ->",nl}),
628
InnerType = asn1ct_gen:get_inner(Type#type.def),
629
emit({nl,"%% attribute number ",Pos," with type ",
631
NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
632
gen_enc_line(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
635
gen_enc_component_mandatory(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
636
InnerType = asn1ct_gen:get_inner(Type#type.def),
637
emit({nl,"%% attribute number ",Pos," with type ",
639
gen_enc_line(TopType,Cname,Type,[],Pos,DynamicEnc,Ext).
641
gen_enc_line(TopType, Cname, Type, [], Pos,DynamicEnc,Ext) ->
642
% Element = io_lib:format("?RT_PER:cindex(~w,~s,~w)",[Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname]),
643
Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
644
gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
645
gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext) ->
646
Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
647
asn1ct_gen:rt2ct_suffix()])),
650
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
653
asn1ct_gen:get_inner(Type#type.def)
655
% case asn1ct_gen:get_constraint(Type#type.constraint,
656
% tableconstraint_info) of
658
% asn1ct_gen:get_inner(Type#type.def);
663
{ext,Ep1,_} when Pos >= Ep1 ->
664
emit(["?RT_PER:encode_open_type(dummy,?RT_PER:complete("]);
670
{_LeadingAttrName,Fun} ->
671
% case asn1ct_gen:get_constraint(Type#type.constraint,
672
% componentrelation) of
673
case (Type#type.def)#'ObjectClassFieldType'.fieldname of
675
throw({error,{notype,type_from_object,T}});
676
{Name,RestFieldNames} when atom(Name) ->
677
emit({"?RT_PER:encode_open_type([],?RT_PER:complete(",nl}),
678
emit({" ",Fun,"(",{asis,Name},", ",
679
Element,", ",{asis,RestFieldNames},")))"});
681
throw({asn1,{'internal error',Other}})
684
{objectfield,PrimFieldName1,PFNList} ->
686
{_LeadingAttrName,Fun} ->
687
emit({"?RT_PER:encode_open_type([],"
688
"?RT_PER:complete(",nl}),
689
emit({" ",Fun,"(",{asis,PrimFieldName1},
690
", ",Element,", ",{asis,PFNList},")))"})
693
CurrMod = get(currmod),
694
case asn1ct_gen:type(Atype) of
695
#'Externaltypereference'{module=Mod,type=EType} when
697
emit({"'enc_",EType,"'(",Element,")"});
698
#'Externaltypereference'{module=Mod,type=EType} ->
699
emit({"'",Mod,"':'enc_",
700
EType,"'(",Element,")"});
701
#typereference{val=Ename} ->
702
emit({"'enc_",Ename,"'(",Element,")"});
704
emit({"'enc_",Atype,"'(",Element,")"});
708
{fixedtypevaluefield,_,Btype} ->
713
gen_encode_prim_wrapper(Ctgenmod,per,EncType,
715
% Ctgenmod:gen_encode_prim(per,EncType,
718
case Type#type.def of
719
#'ObjectClassFieldType'{type=OpenType} ->
720
gen_encode_prim_wrapper(Ctgenmod,per,
724
gen_encode_prim_wrapper(Ctgenmod,per,Type,
727
% Ctgenmod:gen_encode_prim(per,Type,
730
NewTypename = [Cname|TopType],
731
case {Type#type.tablecinf,DynamicEnc} of
732
{[{objfun,_}|_R],{_,EncFun}} ->
733
%% emit({"?RT_PER:encode_open_type([],",
734
%% "?RT_PER:complete(",nl}),
736
asn1ct_gen:list2name(NewTypename),
737
"'(",Element,", ",EncFun,")"});
740
asn1ct_gen:list2name(NewTypename),
746
{ext,Ep2,_} when Pos >= Ep2 ->
751
gen_dec_components_call(TopType,{CompList,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
752
%% The type has extensionmarker
753
{Rpos,AccTerm,AccBytes} =
754
gen_dec_components_call1(TopType, CompList, 1, 1, MaybeComma,DecInfObj,
755
noext,[],[],NumberOfOptionals),
756
emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
757
emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
758
asn1ct_name:new(bytes),
759
{_Epos,AccTermE,AccBytesE} =
760
gen_dec_components_call1(TopType,ExtList,Rpos, 1, "",DecInfObj,Ext,[],[],NumberOfOptionals),
765
emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",",
766
length(ExtList)+1,",Extensions)",nl]),
767
asn1ct_name:new(bytes),
768
{AccTerm++AccTermE,AccBytes++AccBytesE};
770
gen_dec_components_call(TopType,CompList,MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
771
%% The type has no extensionmarker
772
{_,AccTerm,AccBytes} =
773
gen_dec_components_call1(TopType, CompList, 1, 1,MaybeComma,DecInfObj,Ext,[],[],NumberOfOptionals),
777
gen_dec_components_call1(TopType,
778
[C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
779
Tpos,OptPos,MaybeComma,DecInfObj,Ext,AccTerm,AccBytes,NumberOfOptionals) ->
782
{ext,Epos,_Enum} -> Tpos - Epos + 1
785
%% asn1ct_name:new(term),
787
case Type#type.def of
788
#'ObjectClassFieldType'{type=InType} ->
791
asn1ct_gen:get_inner(Def)
793
% case asn1ct_gen:get_constraint(Type#type.constraint,
794
% tableconstraint_info) of
796
% asn1ct_gen:get_inner(Type#type.def);
801
#'Externaltypereference'{type=T} ->
802
emit({nl,"%% attribute number ",Tpos," with type ",
805
emit({nl,"%% attribute number ",Tpos," with type ",
808
emit({nl,"%% attribute number ",Tpos," with type ",
814
asn1ct_name:new(term),
815
asn1ct_name:new(tmpterm),
816
emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
818
asn1ct_name:new(term),
819
asn1ct_name:new(tmpterm),
820
emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
822
asn1ct_name:new(term),
823
emit({"{",{curr,term},",",{next,bytes},"} = "})
828
{noext,mandatory} -> OptPos; % generate nothing
830
Element = io_lib:format("Opt band (1 bsl ~w)",[NumberOfOptionals - OptPos]),
831
emit({"case ",Element," of",nl}),
832
emit({"_Opt",OptPos," when _Opt",OptPos," > 0 ->"}),
835
emit(["case Extensions of",nl]),
836
emit(["_ when size(Extensions) >= ",Pos,",element(",Pos,",Extensions) == 1 ->",nl])
838
put(component_type,{true,C}),
839
{TermVar,BytesVar} = gen_dec_line(TopType,Cname,Type,Tpos,DecInfObj,Ext),
840
erase(component_type),
842
{noext,mandatory} -> true; % generate nothing
844
emit([";",nl,"0 ->"]),
845
gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext);
847
emit([";",nl,"_ ->",nl]),
848
gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext)
851
{noext,mandatory} -> true; % generate nothing
858
asn1ct_name:new(bytes),
861
{Pos+1,AccTerm++TermVar,AccBytes++BytesVar};
864
gen_dec_components_call1(TopType,Rest,Tpos+1,NewOptPos,"",DecInfObj,Ext,
865
AccTerm++TermVar,AccBytes++BytesVar,NumberOfOptionals)
868
gen_dec_components_call1(_TopType,[],Pos,_OptPos,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
869
{Pos,AccTerm,AccBytes}.
872
%%gen_dec_component_no_val(TopType,Cname,Type,_,Pos,{ext,Ep,Enum}) when Pos >= Ep ->
873
%% emit({"{asn1_NOEXTVALUE,",{curr,bytes},"}",nl});
874
gen_dec_component_no_val(_,_,_,{'DEFAULT',DefVal},_,_) ->
875
emit(["{",{asis,DefVal},",",{curr,bytes},"}",nl]);
876
gen_dec_component_no_val(_,_,_,'OPTIONAL',_,_) ->
877
emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl});
878
gen_dec_component_no_val(_,_,_,mandatory,_,{ext,_,_}) ->
879
emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl}).
882
gen_dec_line(TopType,Cname,Type,Pos,DecInfObj,Ext) ->
883
Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
884
asn1ct_gen:rt2ct_suffix()])),
887
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
890
asn1ct_gen:get_inner(Type#type.def)
892
% case asn1ct_gen:get_constraint(Type#type.constraint,
893
% tableconstraint_info) of
895
% asn1ct_gen:get_inner(Type#type.def);
899
BytesVar0 = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
900
BytesVar = case Ext of
901
{ext,Ep,_} when Pos >= Ep ->
902
emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,
903
"}=?RT_PER:decode_open_type(",
904
{curr,bytes},",[]),",nl,
905
"{TmpValx",Pos,",_}="]),
906
io_lib:format("TmpVal~p",[Pos]);
913
false -> % This is in a choice with typefield components
914
{Name,RestFieldNames} =
915
(Type#type.def)#'ObjectClassFieldType'.fieldname,
916
% asn1ct_gen:get_constraint(Type#type.constraint,
917
% tableconstraint_info),
918
asn1ct_name:new(tmpterm),
919
asn1ct_name:new(reason),
920
emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
921
"} = ?RT_PER:decode_open_type(",{curr,bytes},
923
emit([indent(2),"case (catch ObjFun(",
925
",",{curr,tmpterm},",telltype,",
926
{asis,RestFieldNames},")) of", nl]),
927
emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
928
emit([indent(6),"exit({'Type not ",
929
"compatible with table constraint', ",
930
{curr,reason},"});",nl]),
931
asn1ct_name:new(tmpterm),
932
emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
933
emit([indent(6),"{",Cname,", {",{curr,tmpterm},", ",
934
{next,bytes},"}}",nl]),
935
emit([indent(2),"end"]),
937
{"got objfun through args","ObjFun"} ->
938
%% this is when the generated code gots the
939
%% objfun though arguments on function
941
{Name,RestFieldNames} =
942
(Type#type.def)#'ObjectClassFieldType'.fieldname,
943
emit(["?RT_PER:decode_open_type(",{curr,bytes},
945
emit([{curr,term}," =",nl,
946
" case (catch ObjFun(",{asis,Name},",",
947
{curr,tmpterm},",telltype,",
948
{asis,RestFieldNames},")) of", nl]),
949
emit([" {'EXIT',",{curr,reason},"} ->",nl]),
950
emit([indent(6),"exit({'Type not ",
951
"compatible with table constraint', ",
952
{curr,reason},"});",nl]),
953
asn1ct_name:new(tmpterm),
954
emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
955
emit([indent(6),{curr,tmpterm},nl]),
956
emit([indent(2),"end"]),
959
emit({"?RT_PER:decode_open_type(",{curr,bytes},
962
(Type#type.def)#'ObjectClassFieldType'.fieldname,
963
% asn1ct_gen:get_constraint(Type#type.constraint,
964
% tableconstraint_info),
965
[{Cname,RefedFieldName,
966
asn1ct_gen:mk_var(asn1ct_name:curr(term)),
967
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
968
get_components_prop()}]
970
{objectfield,PrimFieldName1,PFNList} ->
971
emit({"?RT_PER:decode_open_type(",{curr,bytes},", [])"}),
972
[{Cname,{PrimFieldName1,PFNList},
973
asn1ct_gen:mk_var(asn1ct_name:curr(term)),
974
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
975
get_components_prop()}];
977
CurrMod = get(currmod),
978
case asn1ct_gen:type(Atype) of
979
#'Externaltypereference'{module=CurrMod,type=EType} ->
980
emit({"'dec_",EType,"'(",BytesVar,",telltype)"});
981
#'Externaltypereference'{module=Mod,type=EType} ->
982
emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
986
{fixedtypevaluefield,_,Btype} ->
987
Ctgenmod:gen_dec_prim(per,Btype,
990
Ctgenmod:gen_dec_prim(per,Type,
994
case Type#type.def of
995
#'ObjectClassFieldType'{type=OpenType} ->
996
Ctgenmod:gen_dec_prim(per,#type{def=OpenType},
999
Ctgenmod:gen_dec_prim(per,Type,
1002
#typereference{val=Dname} ->
1003
emit({"'dec_",Dname,"'(",BytesVar,",telltype)"});
1005
emit({"'dec_",Atype,"'(",BytesVar,",telltype)"});
1006
{constructed,bif} ->
1007
NewTypename = [Cname|TopType],
1008
case Type#type.tablecinf of
1010
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
1011
"'(",BytesVar,", telltype, ObjFun)"});
1013
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
1014
"'(",BytesVar,", telltype)"})
1018
{Cname,{_,OSet,UniqueFName,ValIndex}} ->
1019
Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1020
ValueMatch = value_match(ValIndex,Term),
1021
emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
1022
{asis,UniqueFName},", ",ValueMatch,")"});
1029
{ext,Ep2,_} when Pos >= Ep2 ->
1030
emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]);
1033
%% Prepare return value
1036
{[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
1042
gen_enc_choice(TopType,CompList,Ext) ->
1043
gen_enc_choice_tag(CompList, [], Ext),
1045
emit({"case element(1,Val) of",nl}),
1046
gen_enc_choice2(TopType, CompList, Ext),
1049
gen_enc_choice_tag({C1,C2},_,_) ->
1050
N1 = get_name_list(C1),
1051
N2 = get_name_list(C2),
1052
emit(["?RT_PER:set_choice(element(1,Val),",
1053
{asis,{N1,N2}},", ",{asis,{length(N1),length(N2)}},")"]);
1054
gen_enc_choice_tag(C,_,_) ->
1055
N = get_name_list(C),
1056
emit(["?RT_PER:set_choice(element(1,Val),",
1057
{asis,N},", ",{asis,length(N)},")"]).
1060
get_name_list(L,[]).
1062
get_name_list([#'ComponentType'{name=Name}|T], Acc) ->
1063
get_name_list(T,[Name|Acc]);
1064
get_name_list([], Acc) ->
1067
%gen_enc_choice_tag([H|T],Acc,Ext) when record(H,'ComponentType') ->
1068
% gen_enc_choice_tag(T,[H#'ComponentType'.name|Acc],Ext);
1069
%gen_enc_choice_tag([H|T],Acc,Ext) -> % skip EXTENSIONMARK
1070
% gen_enc_choice_tag(T,Acc,Ext);
1071
%gen_enc_choice_tag([],Acc,Ext) ->
1072
% Length = length(Acc),
1073
% emit({"?RT_PER:set_choice(element(1,Val),",{asis,Length},",",
1074
% {asis,lists:reverse(Acc)},",",{asis,Ext},")"}),
1077
gen_enc_choice2(TopType, {L1,L2}, Ext) ->
1078
gen_enc_choice2(TopType, L1 ++ L2, 0, Ext);
1079
gen_enc_choice2(TopType, L, Ext) ->
1080
gen_enc_choice2(TopType, L, 0, Ext).
1082
gen_enc_choice2(TopType,[H1,H2|T], Pos, Ext)
1083
when record(H1,'ComponentType'), record(H2,'ComponentType') ->
1084
Cname = H1#'ComponentType'.name,
1085
Type = H1#'ComponentType'.typespec,
1087
% case asn1ct_gen:get_constraint(Type#type.constraint,
1088
% tableconstraint_info) of
1092
% {no_attr,"ObjFun"}
1094
case asn1ct_gen:get_constraint(Type#type.constraint,
1095
componentrelation) of
1097
_ -> {no_attr,"ObjFun"}
1099
emit({{asis,Cname}," ->",nl}),
1100
gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
1102
gen_enc_choice2(TopType,[H2|T], Pos+1, Ext);
1103
gen_enc_choice2(TopType,[H1|T], Pos, Ext) when record(H1,'ComponentType') ->
1104
Cname = H1#'ComponentType'.name,
1105
Type = H1#'ComponentType'.typespec,
1107
% case asn1ct_gen:get_constraint(Type#type.constraint,
1108
% tableconstraint_info) of
1112
% {no_attr,"ObjFun"}
1114
case asn1ct_gen:get_constraint(Type#type.constraint,
1115
componentrelation) of
1117
_ -> {no_attr,"ObjFun"}
1119
emit({{asis,H1#'ComponentType'.name}," ->",nl}),
1120
gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
1121
gen_enc_choice2(TopType,T, Pos+1, Ext);
1122
gen_enc_choice2(_,[], _, _) ->
1125
gen_dec_choice(TopType,CompList,{ext,Pos,NumExt}) ->
1126
emit({"{Ext,",{curr,bytes},"} = ?RT_PER:getbit(Bytes),",nl}),
1127
asn1ct_name:new(bytes),
1128
gen_dec_choice1(TopType,CompList,{ext,Pos,NumExt});
1129
gen_dec_choice(TopType,CompList,noext) ->
1130
gen_dec_choice1(TopType,CompList,noext).
1132
gen_dec_choice1(TopType,CompList,noext) ->
1133
emit({"{Choice,",{curr,bytes},
1134
"} = ?RT_PER:getchoice(",{prev,bytes},",",
1135
length(CompList),", 0),",nl}),
1136
emit({"{Cname,{Val,NewBytes}} = case Choice of",nl}),
1137
gen_dec_choice2(TopType,CompList,noext),
1138
emit({nl,"end,",nl}),
1139
emit({nl,"{{Cname,Val},NewBytes}"});
1140
gen_dec_choice1(TopType,{RootList,ExtList},Ext) ->
1141
NewList = RootList ++ ExtList,
1142
gen_dec_choice1(TopType, NewList, Ext);
1143
gen_dec_choice1(TopType,CompList,{ext,ExtPos,ExtNum}) ->
1144
emit({"{Choice,",{curr,bytes},
1145
"} = ?RT_PER:getchoice(",{prev,bytes},",",
1146
length(CompList)-ExtNum,",Ext ),",nl}),
1147
emit({"{Cname,{Val,NewBytes}} = case Choice + Ext*",ExtPos-1," of",nl}),
1148
gen_dec_choice2(TopType,CompList,{ext,ExtPos,ExtNum}),
1149
emit([";",nl,"_ -> {asn1_ExtAlt, ?RT_PER:decode_open_type(",{curr,bytes},",[])}"]),
1150
emit({nl,"end,",nl}),
1151
emit({nl,"{{Cname,Val},NewBytes}"}).
1154
gen_dec_choice2(TopType,L,Ext) ->
1155
gen_dec_choice2(TopType,L,0,Ext).
1157
gen_dec_choice2(TopType,[H1,H2|T],Pos,Ext)
1158
when record(H1,'ComponentType'), record(H2,'ComponentType') ->
1159
Cname = H1#'ComponentType'.name,
1160
Type = H1#'ComponentType'.typespec,
1161
case Type#type.def of
1162
#'ObjectClassFieldType'{type={typefield,_}} ->
1163
emit({Pos," -> ",nl}),
1164
wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
1167
emit({Pos," -> {",{asis,Cname},",",nl}),
1168
wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
1171
gen_dec_choice2(TopType,[H2|T],Pos+1,Ext);
1172
gen_dec_choice2(TopType,[H1,_H2|T],Pos,Ext) when record(H1,'ComponentType') ->
1173
gen_dec_choice2(TopType,[H1|T],Pos,Ext); % skip extensionmark
1174
gen_dec_choice2(TopType,[H1|T],Pos,Ext) when record(H1,'ComponentType') ->
1175
Cname = H1#'ComponentType'.name,
1176
Type = H1#'ComponentType'.typespec,
1177
case Type#type.def of
1178
#'ObjectClassFieldType'{type={typefield,_}} ->
1179
emit({Pos," -> ",nl}),
1180
wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext);
1182
emit({Pos," -> {",{asis,Cname},",",nl}),
1183
wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
1186
gen_dec_choice2(TopType,[T],Pos+1);
1187
gen_dec_choice2(TopType,[_|T],Pos,Ext) ->
1188
gen_dec_choice2(TopType,T,Pos,Ext);% skip extensionmark
1189
gen_dec_choice2(_,[],Pos,_) ->
1193
lists:duplicate(N,32). % 32 = space
1195
gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) ->
1196
% put(component_type,true), % add more info in component_type
1197
CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value).
1198
% erase(component_type).
1200
make_element(I,Val,Cname) ->
1201
case lists:member(optimize,get(encoding_options)) of
1203
io_lib:format("?RT_PER:cindex(~w,~s,~w)",[I,Val,Cname]);
1205
io_lib:format("element(~w,~s)",[I,Val])
1208
wrap_gen_dec_line(C,TopType,Cname,Type,Pos,DIO,Ext) ->
1209
put(component_type,{true,C}),
1210
gen_dec_line(TopType,Cname,Type,Pos,DIO,Ext),
1211
erase(component_type).
1213
get_components_prop() ->
1214
case get(component_type) of
1217
{true,#'ComponentType'{prop=Prop}} -> Prop
1221
value_match(Index,Value) when atom(Value) ->
1222
value_match(Index,atom_to_list(Value));
1223
value_match([],Value) ->
1225
value_match([{VI,_}|VIs],Value) ->
1226
value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
1227
value_match1(Value,[],Acc,Depth) ->
1228
Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
1229
value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
1230
value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
1232
notice_value_match() ->
1233
Module = get(currmod),
1234
put(value_match,{true,Module}).