1%% ``Licensed under the Apache License, Version 2.0 (the "License");
2%% you may not use this file except in compliance with the License.
3%% You may obtain a copy of the License at
4%%
5%%     http://www.apache.org/licenses/LICENSE-2.0
6%%
7%% Unless required by applicable law or agreed to in writing, software
8%% distributed under the License is distributed on an "AS IS" BASIS,
9%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10%% See the License for the specific language governing permissions and
11%% limitations under the License.
12%%
13%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
14%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
15%% AB. All Rights Reserved.''
16%%
17%%     $Id: asn1ct_constructed_per.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
18%%
19-module(asn1ct_constructed_per).
20
21-export([gen_encode_sequence/3]).
22-export([gen_decode_sequence/3]).
23-export([gen_encode_set/3]).
24-export([gen_decode_set/3]).
25-export([gen_encode_sof/4]).
26-export([gen_decode_sof/4]).
27-export([gen_encode_choice/3]).
28-export([gen_decode_choice/3]).
29
30-include("asn1_records.hrl").
31%-compile(export_all).
32
33-import(asn1ct_gen, [emit/1,demit/1]).
34
35
36%% ENCODE GENERATOR FOR SEQUENCE TYPE  ** **********
37
38
39gen_encode_set(Erules,TypeName,D) ->
40    gen_encode_constructed(Erules,TypeName,D).
41
42gen_encode_sequence(Erules,TypeName,D) ->
43    gen_encode_constructed(Erules,TypeName,D).
44
45gen_encode_constructed(Erules,Typename,D) when record(D,type) ->
46    asn1ct_name:start(),
47    asn1ct_name:new(term),
48    asn1ct_name:new(bytes),
49    {CompList,TableConsInfo} =
50	case D#type.def of
51	    #'SEQUENCE'{tablecinf=TCI,components=CL} ->
52		{CL,TCI};
53	    #'SET'{tablecinf=TCI,components=CL} ->
54		{CL,TCI}
55	end,
56    case Typename of
57	['EXTERNAL'] ->
58	    emit({{var,asn1ct_name:next(val)},
59		  " = asn1rt_check:transform_to_EXTERNAL1990(",
60		  {var,asn1ct_name:curr(val)},"),",nl}),
61	    asn1ct_name:new(val);
62	_ ->
63	    ok
64    end,
65    case {Optionals = optionals(CompList),CompList} of
66	{[],EmptyCL} when EmptyCL == {[],[]};EmptyCL == [] ->
67	    emit(["%%Variable setting just to eliminate ",
68		  "compiler warning for unused vars!",nl,
69		  "_Val = ",{var,asn1ct_name:curr(val)},",",nl]);
70	{[],_} ->
71	    emit([{var,asn1ct_name:next(val)}," = ?RT_PER:list_to_record("]),
72	    emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
73	    emit([", ",{var,asn1ct_name:curr(val)},"),",nl]);
74	_ ->
75	    Fixoptcall =
76		case Erules of
77		    per -> ",Opt} = ?RT_PER:fixoptionals2(";
78		    _ -> ",Opt} = ?RT_PER:fixoptionals("
79		end,
80	    emit({"{",{var,asn1ct_name:next(val)},Fixoptcall,
81		  {asis,Optionals},",",length(Optionals),
82		  ",",{var,asn1ct_name:curr(val)},"),",nl})
83    end,
84    asn1ct_name:new(val),
85    Ext = extensible(CompList),
86    case Ext of
87	{ext,_,NumExt} when NumExt > 0 ->
88	    emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},
89		  ", ",{curr,val},"),",nl]);
90	_ -> true
91    end,
92    EncObj =
93	case TableConsInfo of
94	    #simpletableattributes{usedclassfield=Used,
95				   uniqueclassfield=Unique} when Used /= Unique ->
96		false;
97	    %% ObjectSet, name of the object set in constraints
98	    %%
99	    %%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint
100	    #simpletableattributes{objectsetname=ObjectSet,
101				   c_name=AttrN,
102				   c_index=N,
103				   usedclassfield=UniqueFieldName,
104				   uniqueclassfield=UniqueFieldName,
105				   valueindex=ValueIndex
106				  } -> %% N is index of attribute that determines constraint
107		OSDef =
108		    case ObjectSet of
109			{Module,OSName} ->
110			    asn1_db:dbget(Module,OSName);
111			OSName ->
112			    asn1_db:dbget(get(currmod),OSName)
113		    end,
114		case (OSDef#typedef.typespec)#'ObjectSet'.gen of
115		    true ->
116			ObjectEncode =
117			    asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
118			emit([ObjectEncode," = ",nl]),
119			emit(["  'getenc_",ObjectSet,"'(",
120			      {asis,UniqueFieldName},", ",nl]),
121			El = make_element(N+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),AttrN),
122			Indent = 12 + length(atom_to_list(ObjectSet)),
123			case ValueIndex of
124			    [] ->
125				emit([indent(Indent),El,"),",nl]);
126			    _ ->
127				emit([indent(Indent),"value_match(",
128				      {asis,ValueIndex},",",El,")),",nl]),
129				notice_value_match()
130			end,
131			{AttrN,ObjectEncode};
132		    _ ->
133			false
134		end;
135	    _  ->
136		case D#type.tablecinf of
137		    [{objfun,_}|_] ->
138			%% when the simpletableattributes was at an outer
139			%% level and the objfun has been passed through the
140			%% function call
141			{"got objfun through args","ObjFun"};
142		    _ ->
143			false
144		end
145	end,
146    emit({"[",nl}),
147    MaybeComma1 =
148	case Ext of
149	    {ext,_Pos,NumExt2} when NumExt2 > 0 ->
150		emit({"?RT_PER:setext(Extensions =/= [])"}),
151		", ";
152	    {ext,_Pos,_} ->
153		emit({"?RT_PER:setext(false)"}),
154		", ";
155	    _ ->
156		""
157	end,
158    MaybeComma2 =
159	case optionals(CompList) of
160	    [] -> MaybeComma1;
161	    _ ->
162		emit(MaybeComma1),
163		emit("Opt"),
164		{",",nl}
165	end,
166    gen_enc_components_call(Typename,CompList,MaybeComma2,EncObj,Ext),
167    emit({"].",nl}).
168
169
170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171%% generate decode function for SEQUENCE and SET
172%%
173gen_decode_set(Erules,Typename,D) ->
174    gen_decode_constructed(Erules,Typename,D).
175
176gen_decode_sequence(Erules,Typename,D) ->
177    gen_decode_constructed(Erules,Typename,D).
178
179gen_decode_constructed(_Erules,Typename,D) when record(D,type) ->
180    asn1ct_name:start(),
181    {CompList,TableConsInfo} =
182	case D#type.def of
183	    #'SEQUENCE'{tablecinf=TCI,components=CL} ->
184		{CL,TCI};
185	    #'SET'{tablecinf=TCI,components=CL} ->
186		{CL,TCI}
187	end,
188    Ext = extensible(CompList),
189    MaybeComma1 = case Ext of
190		      {ext,_Pos,_NumExt} ->
191			  gen_dec_extension_value("Bytes"),
192			  {",",nl};
193		      _ ->
194			  ""
195		  end,
196    Optionals = optionals(CompList),
197    MaybeComma2 = case Optionals of
198		      [] -> MaybeComma1;
199		      _ ->
200			  Bcurr = asn1ct_name:curr(bytes),
201			  Bnext = asn1ct_name:next(bytes),
202			  emit(MaybeComma1),
203			  GetoptCall = "} = ?RT_PER:getoptionals2(",
204			  emit({"{Opt,",{var,Bnext},GetoptCall,
205				{var,Bcurr},",",{asis,length(Optionals)},")"}),
206			  asn1ct_name:new(bytes),
207			  ", "
208		  end,
209    {DecObjInf,UniqueFName,ValueIndex} =
210	case TableConsInfo of
211%%	    {ObjectSet,AttrN,N,UniqueFieldName} ->%% N is index of attribute that determines constraint
212	    #simpletableattributes{objectsetname=ObjectSet,
213				   c_name=AttrN,
214				   usedclassfield=UniqueFieldName,
215				   uniqueclassfield=UniqueFieldName,
216				   valueindex=ValIndex} ->
217%%		{AttrN,ObjectSet};
218		F = fun(#'ComponentType'{typespec=CT})->
219			    case {CT#type.constraint,CT#type.tablecinf} of
220				{[],[{objfun,_}|_R]} -> true;
221				_ -> false
222			    end
223		    end,
224		case lists:any(F,CompList) of
225		    true -> % when component relation constraint establish
226			%% relation from a component to another components
227			%% subtype component
228			{{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
229			 UniqueFieldName,ValIndex};
230		    false ->
231			{{AttrN,ObjectSet},UniqueFieldName,ValIndex}
232		end;
233	    _ ->
234		case D#type.tablecinf of
235		    [{objfun,_}|_] ->
236			{{"got objfun through args","ObjFun"},false,false};
237		    _ ->
238			{false,false,false}
239		end
240	end,
241    {AccTerm,AccBytes} =
242	gen_dec_components_call(Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
243    case asn1ct_name:all(term) of
244	[] -> emit(MaybeComma2); % no components at all
245	_ -> emit({com,nl})
246    end,
247    case {AccTerm,AccBytes} of
248	{[],[]} ->
249	    ok;
250	{_,[]} ->
251	    ok;
252	{[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
253	    DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
254	    ValueMatch = value_match(ValueIndex,Term),
255	    emit({DecObj," =",nl,"   'getdec_",ObjSet,"'(",
256%		  {asis,UniqueFName},", ",Term,"),",nl}),
257		  {asis,UniqueFName},", ",ValueMatch,"),",nl}),
258	    gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
259    end,
260    %% we don't return named lists any more   Cnames = mkcnamelist(CompList),
261    demit({"Result = "}), %dbg
262    %% return value as record
263    case Typename of
264	['EXTERNAL'] ->
265	    emit({"   OldFormat={'",asn1ct_gen:list2rname(Typename),
266		  "'"}),
267	    mkvlist(asn1ct_name:all(term)),
268	    emit({"},",nl}),
269	    emit({"   ASN11994Format =",nl,
270		  "      asn1rt_check:transform_to_EXTERNAL1994",
271		  "(OldFormat),",nl}),
272	    emit("   {ASN11994Format,");
273	_ ->
274	    emit(["{{'",asn1ct_gen:list2rname(Typename),"'"]),
275	    mkvlist(asn1ct_name:all(term)),
276	    emit("},")
277    end,
278    emit({{var,asn1ct_name:curr(bytes)},"}"}),
279    emit({".",nl,nl}).
280
281gen_dec_listofopentypes(_,[],_) ->
282    emit(nl);
283gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
284
285%    asn1ct_name:new(term),
286    asn1ct_name:new(tmpterm),
287    asn1ct_name:new(reason),
288
289    emit([Term," = ",nl]),
290
291    N = case Prop of
292	    mandatory -> 0;
293	    'OPTIONAL' ->
294		emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
295		6;
296	    {'DEFAULT',Val} ->
297		emit_opt_or_mand_check(Val,TmpTerm),
298		6
299	end,
300
301    emit([indent(N+3),"case (catch ",DecObj,"(",
302	  {asis,FirstPFN},", ",TmpTerm,", telltype,",{asis,PFNList},")) of",nl]),
303    emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
304%%    emit({indent(9),"throw({runtime_error,{","'Type not compatible with table constraint'",",",Term,"}});",nl}),
305    emit([indent(N+9),"exit({'Type not compatible with table constraint',",
306	  {curr,reason},"});",nl]),
307    emit([indent(N+6),"{",{curr,tmpterm},",_} ->",nl]),
308    emit([indent(N+9),{curr,tmpterm},nl]),
309
310    case Prop of
311	mandatory ->
312	    emit([indent(N+3),"end,",nl]);
313	_ ->
314	    emit([indent(N+3),"end",nl,
315		  indent(3),"end,",nl])
316    end,
317    gen_dec_listofopentypes(DecObj,Rest,true).
318
319
320emit_opt_or_mand_check(Val,Term) ->
321    emit([indent(3),"case ",Term," of",nl,
322	  indent(6),{asis,Val}," ->",{asis,Val},";",nl,
323	  indent(6),"_ ->",nl]).
324
325%% ENCODE GENERATOR FOR THE CHOICE TYPE *******
326%% assume Val = {Alternative,AltType}
327%% generate
328%%[
329%% ?RT_PER:set_choice(element(1,Val),Altnum,Altlist,ext),
330%%case element(1,Val) of
331%%    alt1 ->
332%%	encode_alt1(element(2,Val));
333%%    alt2 ->
334%%	encode_alt2(element(2,Val))
335%%end
336%%].
337
338gen_encode_choice(_Erules,Typename,D) when record(D,type) ->
339    {'CHOICE',CompList} = D#type.def,
340    emit({"[",nl}),
341    Ext = extensible(CompList),
342    gen_enc_choice(Typename,CompList,Ext),
343    emit({nl,"].",nl}).
344
345gen_decode_choice(_Erules,Typename,D) when record(D,type) ->
346    asn1ct_name:start(),
347    asn1ct_name:new(bytes),
348    {'CHOICE',CompList} = D#type.def,
349    Ext = extensible(CompList),
350    gen_dec_choice(Typename,CompList,Ext),
351    emit({".",nl}).
352
353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354% Encode generator for SEQUENCE OF type
355
356
357gen_encode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
358    asn1ct_name:start(),
359% Val = [Component]
360% ?RT_PER:encode_length(length(Val)),
361% lists:
362    {_SeqOrSetOf,ComponentType} = D#type.def,
363    emit({"[",nl}),
364    SizeConstraint =
365	case asn1ct_gen:get_constraint(D#type.constraint,
366				       'SizeConstraint') of
367	    no -> undefined;
368	    Range -> Range
369	end,
370    ObjFun =
371	case D#type.tablecinf of
372	    [{objfun,_}|_R] ->
373		", ObjFun";
374	    _->
375		""
376	end,
377    emit({nl,indent(3),"?RT_PER:encode_length(",
378	  {asis,SizeConstraint},
379	  ",length(Val)),",nl}),
380    emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
381	      "_components'(Val",ObjFun,", [])"}),
382    emit({nl,"].",nl}),
383    NewComponentType =
384	case ComponentType#type.def of
385	    {'ENUMERATED',_,Component}->
386		ComponentType#type{def={'ENUMERATED',Component}};
387	    _ -> ComponentType
388	end,
389    gen_encode_sof_components(Typename,SeqOrSetOf,NewComponentType).
390
391gen_decode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
392    asn1ct_name:start(),
393% Val = [Component]
394% ?RT_PER:encode_length(length(Val)),
395% lists:
396    {_SeqOrSetOf,ComponentType} = D#type.def,
397    SizeConstraint =
398	case asn1ct_gen:get_constraint(D#type.constraint,
399				       'SizeConstraint') of
400	    no -> undefined;
401	    Range -> Range
402	end,
403    ObjFun =
404	case D#type.tablecinf of
405	    [{objfun,_}|_R] ->
406		", ObjFun";
407	    _ ->
408		""
409	end,
410    emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",{asis,SizeConstraint},"),",nl}),
411    emit({"'dec_",asn1ct_gen:list2name(Typename),
412	      "_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
413    NewComponentType =
414	case ComponentType#type.def of
415	    {'ENUMERATED',_,Component}->
416		ComponentType#type{def={'ENUMERATED',Component}};
417	    _ -> ComponentType
418	end,
419    gen_decode_sof_components(Typename,SeqOrSetOf,NewComponentType).
420
421gen_encode_sof_components(Typename,SeqOrSetOf,Cont) ->
422    {ObjFun,ObjFun_Var} =
423	case Cont#type.tablecinf of
424	    [{objfun,_}|_R] ->
425		{", ObjFun",", _"};
426	    _ ->
427		{"",""}
428	end,
429    emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([]",
430	  ObjFun_Var,", Acc) -> lists:reverse(Acc);",nl,nl}),
431    emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([H|T]",
432	  ObjFun,", Acc) ->",nl}),
433    emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'(T"}),
434    emit({ObjFun,", ["}),
435    %% the component encoder
436    Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
437						       Cont#type.def),
438
439    Conttype = asn1ct_gen:get_inner(Cont#type.def),
440    Currmod = get(currmod),
441    Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
442					  asn1ct_gen:rt2ct_suffix()])),
443    case asn1ct_gen:type(Conttype) of
444	{primitive,bif} ->
445	    gen_encode_prim_wrapper(Ctgenmod,per,Cont,false,"H");
446% 	    Ctgenmod:gen_encode_prim(per,Cont,false,"H");
447	{constructed,bif} ->
448	    NewTypename = [Constructed_Suffix|Typename],
449	    emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
450		  ObjFun,")",nl,nl});
451	#'Externaltypereference'{module=Currmod,type=Ename} ->
452	    emit({"'enc_",Ename,"'(H)",nl,nl});
453	#'Externaltypereference'{module=EMod,type=EType} ->
454	    emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
455	_ ->
456	    emit({"'enc_",Conttype,"'(H)",nl,nl})
457    end,
458    emit({" | Acc]).",nl}).
459
460gen_decode_sof_components(Typename,SeqOrSetOf,Cont) ->
461    {ObjFun,ObjFun_Var} =
462	case Cont#type.tablecinf of
463	    [{objfun,_}|_R] ->
464		{", ObjFun",", _"};
465	    _ ->
466		{"",""}
467	end,
468    emit({"'dec_",asn1ct_gen:list2name(Typename),
469	  "_components'(0, Bytes, _",ObjFun_Var,", Acc) ->",nl,
470	  indent(3),"{lists:reverse(Acc), Bytes};",nl}),
471    emit({"'dec_",asn1ct_gen:list2name(Typename),
472	  "_components'(Num, Bytes, _",ObjFun,", Acc) ->",nl}),
473    emit({indent(3),"{Term,Remain} = "}),
474    Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
475						       Cont#type.def),
476    Conttype = asn1ct_gen:get_inner(Cont#type.def),
477    Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
478					  asn1ct_gen:rt2ct_suffix()])),
479    case asn1ct_gen:type(Conttype) of
480	{primitive,bif} ->
481	    Ctgenmod:gen_dec_prim(per,Cont,"Bytes"),
482	    emit({com,nl});
483	{constructed,bif} ->
484	    NewTypename = [Constructed_Suffix|Typename],
485	    emit({"'dec_",asn1ct_gen:list2name(NewTypename),
486		  "'(Bytes, telltype",ObjFun,"),",nl});
487	#typereference{val=Dname} ->
488	    emit({"'dec_",Dname,"'(Bytes,telltype),",nl});
489	#'Externaltypereference'{module=EMod,type=EType} ->
490	    emit({"'",EMod,"':'dec_",EType,"'(Bytes,telltype),",nl});
491	_ ->
492	    emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
493    end,
494    emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
495	  "_components'(Num-1, Remain, telltype",ObjFun,", [Term|Acc]).",nl}).
496
497
498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499% General and special help functions (not exported)
500
501mkvlist([H|T]) ->
502    emit(","),
503    mkvlist2([H|T]);
504mkvlist([]) ->
505    true.
506mkvlist2([H,T1|T]) ->
507    emit({{var,H},","}),
508    mkvlist2([T1|T]);
509mkvlist2([H|T]) ->
510    emit({{var,H}}),
511    mkvlist2(T);
512mkvlist2([]) ->
513    true.
514
515extensible(CompList) when list(CompList) ->
516    noext;
517extensible({RootList,ExtList}) ->
518    {ext,length(RootList)+1,length(ExtList)}.
519
520gen_dec_extension_value(_) ->
521    emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
522    asn1ct_name:new(bytes).
523
524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525%% Produce a list with positions (in the Value record) where
526%% there are optional components, start with 2 because first element
527%% is the record name
528
529optionals({L,_Ext}) -> optionals(L,[],2);
530optionals(L) -> optionals(L,[],2).
531
532optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
533    optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
534optionals([#'ComponentType'{prop='OPTIONAL'}|Rest],Acc,Pos) ->
535		 optionals(Rest,[Pos|Acc],Pos+1);
536optionals([#'ComponentType'{prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
537		 optionals(Rest,[Pos|Acc],Pos+1);
538optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
539		 optionals(Rest,Acc,Pos+1);
540optionals([],Acc,_) ->
541    lists:reverse(Acc).
542
543
544gen_enc_components_call(TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) ->
545    %% The type has extensionmarker
546    Rpos = gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,noext),
547    case Ext of
548	{ext,_,ExtNum} when ExtNum > 0 ->
549	    emit([nl,
550		  ",Extensions",nl]);
551	_ -> true
552    end,
553    %handle extensions
554    gen_enc_components_call1(TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext);
555gen_enc_components_call(TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
556    %% The type has no extensionmarker
557    gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
558
559gen_enc_components_call1(TopType,
560			 [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
561			 Tpos,
562			 MaybeComma, DynamicEnc, Ext) ->
563
564    put(component_type,{true,C}),
565    %% information necessary in asn1ct_gen_per_rt2ct:gen_encode_prim
566
567    Pos = case Ext of
568	      noext -> Tpos;
569	      {ext,Epos,_Enum} -> Tpos - Epos + 1
570	  end,
571    emit(MaybeComma),
572    case Prop of
573	'OPTIONAL' ->
574	    gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
575	{'DEFAULT',_DefVal} ->
576	    gen_enc_component_default(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
577	_ ->
578	    case Ext of
579		{ext,ExtPos,_} when Tpos >= ExtPos ->
580		    gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
581		_ ->
582		    gen_enc_component_mandatory(TopType,Cname,Type,Tpos,DynamicEnc,Ext)
583	    end
584    end,
585
586    erase(component_type),
587
588    case Rest of
589	[] ->
590	    Pos+1;
591	_ ->
592	    emit({com,nl}),
593	    gen_enc_components_call1(TopType,Rest,Tpos+1,"",DynamicEnc,Ext)
594    end;
595gen_enc_components_call1(_TopType,[],Pos,_,_,_) ->
596	Pos.
597
598gen_enc_component_default(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
599%    Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
600    Element = make_element(Pos+1,"Val1",Cname),
601    emit({"case ",Element," of",nl}),
602%    case Ext of
603%	{ext,ExtPos,_} when Pos >= ExtPos ->
604%	    emit({"asn1_NOEXTVALUE -> [];",nl});
605%	_ ->
606    emit({"asn1_DEFAULT -> [];",nl}),
607%    end,
608    asn1ct_name:new(tmpval),
609    emit({{curr,tmpval}," ->",nl}),
610    InnerType = asn1ct_gen:get_inner(Type#type.def),
611    emit({nl,"%% attribute number ",Pos," with type ",
612	      InnerType,nl}),
613    NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
614    gen_enc_line(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
615    emit({nl,"end"}).
616
617gen_enc_component_optional(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
618%    Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
619    Element = make_element(Pos+1,"Val1",Cname),
620    emit({"case ",Element," of",nl}),
621%    case Ext of
622%	{ext,ExtPos,_} when Pos >= ExtPos ->
623%	    emit({"asn1_NOEXTVALUE -> [];",nl});
624%	_ ->
625    emit({"asn1_NOVALUE -> [];",nl}),
626%    end,
627    asn1ct_name:new(tmpval),
628    emit({{curr,tmpval}," ->",nl}),
629    InnerType = asn1ct_gen:get_inner(Type#type.def),
630    emit({nl,"%% attribute number ",Pos," with type ",
631	      InnerType,nl}),
632    NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
633    gen_enc_line(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
634    emit({nl,"end"}).
635
636gen_enc_component_mandatory(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
637    InnerType = asn1ct_gen:get_inner(Type#type.def),
638    emit({nl,"%% attribute number ",Pos," with type ",
639	      InnerType,nl}),
640    gen_enc_line(TopType,Cname,Type,[],Pos,DynamicEnc,Ext).
641
642gen_enc_line(TopType, Cname, Type, [], Pos,DynamicEnc,Ext) ->
643%    Element = io_lib:format("?RT_PER:cindex(~w,~s,~w)",[Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname]),
644    Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
645    gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
646gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext) ->
647    Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
648					  asn1ct_gen:rt2ct_suffix()])),
649    Atype =
650	case Type of
651	    #type{def=#'ObjectClassFieldType'{type=InnerType}} ->
652		InnerType;
653	    _  ->
654		asn1ct_gen:get_inner(Type#type.def)
655	end,
656% 	case asn1ct_gen:get_constraint(Type#type.constraint,
657% 				       tableconstraint_info) of
658% 	    no ->
659% 		asn1ct_gen:get_inner(Type#type.def);
660% 	    _ ->
661% 		Type#type.def
662% 	end,
663    case Ext of
664	{ext,Ep1,_} when  Pos >= Ep1 ->
665	    emit(["?RT_PER:encode_open_type(dummy,?RT_PER:complete("]);
666	_ -> true
667    end,
668    case Atype of
669	{typefield,_} ->
670	    case DynamicEnc of
671		{_LeadingAttrName,Fun} ->
672% 		    case asn1ct_gen:get_constraint(Type#type.constraint,
673% 						   componentrelation) of
674		    case (Type#type.def)#'ObjectClassFieldType'.fieldname of
675			{notype,T} ->
676			    throw({error,{notype,type_from_object,T}});
677			{Name,RestFieldNames} when atom(Name) ->
678			    emit({"?RT_PER:encode_open_type([],?RT_PER:complete(",nl}),
679			    emit({"   ",Fun,"(",{asis,Name},", ",
680				  Element,", ",{asis,RestFieldNames},")))"});
681			Other ->
682			    throw({asn1,{'internal error',Other}})
683		    end
684	    end;
685	{objectfield,PrimFieldName1,PFNList} ->
686	    case DynamicEnc of
687		{_LeadingAttrName,Fun} ->
688		    emit({"?RT_PER:encode_open_type([],"
689			  "?RT_PER:complete(",nl}),
690		    emit({"   ",Fun,"(",{asis,PrimFieldName1},
691			  ", ",Element,", ",{asis,PFNList},")))"})
692	    end;
693	_ ->
694	    CurrMod = get(currmod),
695	    case asn1ct_gen:type(Atype) of
696		#'Externaltypereference'{module=Mod,type=EType} when
697		      (CurrMod==Mod) ->
698		    emit({"'enc_",EType,"'(",Element,")"});
699		#'Externaltypereference'{module=Mod,type=EType} ->
700		    emit({"'",Mod,"':'enc_",
701			  EType,"'(",Element,")"});
702		#typereference{val=Ename} ->
703		    emit({"'enc_",Ename,"'(",Element,")"});
704		{notype,_} ->
705		    emit({"'enc_",Atype,"'(",Element,")"});
706		{primitive,bif} ->
707		    EncType =
708			case Atype of
709			    {fixedtypevaluefield,_,Btype} ->
710				Btype;
711			    _ ->
712				Type
713			end,
714		    gen_encode_prim_wrapper(Ctgenmod,per,EncType,
715					    false,Element);
716% 		    Ctgenmod:gen_encode_prim(per,EncType,
717% 					     false,Element);
718		'ASN1_OPEN_TYPE' ->
719		    case Type#type.def of
720			#'ObjectClassFieldType'{type=OpenType} ->
721			    gen_encode_prim_wrapper(Ctgenmod,per,
722						    #type{def=OpenType},
723						    false,Element);
724			_ ->
725			    gen_encode_prim_wrapper(Ctgenmod,per,Type,
726						    false,Element)
727		    end;
728% 		    Ctgenmod:gen_encode_prim(per,Type,
729% 					     false,Element);
730		{constructed,bif} ->
731		    NewTypename = [Cname|TopType],
732		    case {Type#type.tablecinf,DynamicEnc} of
733			{[{objfun,_}|_R],{_,EncFun}} ->
734%%			    emit({"?RT_PER:encode_open_type([],",
735%%				  "?RT_PER:complete(",nl}),
736			    emit({"'enc_",
737				  asn1ct_gen:list2name(NewTypename),
738				  "'(",Element,", ",EncFun,")"});
739			_ ->
740			    emit({"'enc_",
741				  asn1ct_gen:list2name(NewTypename),
742				  "'(",Element,")"})
743		    end
744	    end
745    end,
746    case Ext of
747	{ext,Ep2,_} when Pos >= Ep2 ->
748	    emit(["))"]);
749	_ -> true
750    end.
751
752gen_dec_components_call(TopType,{CompList,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
753    %% The type has extensionmarker
754    {Rpos,AccTerm,AccBytes} =
755	gen_dec_components_call1(TopType, CompList, 1, 1, MaybeComma,DecInfObj,
756				 noext,[],[],NumberOfOptionals),
757    emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
758    emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
759    asn1ct_name:new(bytes),
760    {_Epos,AccTermE,AccBytesE} =
761	gen_dec_components_call1(TopType,ExtList,Rpos, 1, "",DecInfObj,Ext,[],[],NumberOfOptionals),
762    case ExtList of
763	[] -> true;
764	_ -> emit([",",nl])
765    end,
766    emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",",
767	  length(ExtList)+1,",Extensions)",nl]),
768    asn1ct_name:new(bytes),
769    {AccTerm++AccTermE,AccBytes++AccBytesE};
770
771gen_dec_components_call(TopType,CompList,MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
772    %% The type has no extensionmarker
773    {_,AccTerm,AccBytes} =
774	gen_dec_components_call1(TopType, CompList, 1, 1,MaybeComma,DecInfObj,Ext,[],[],NumberOfOptionals),
775    {AccTerm,AccBytes}.
776
777
778gen_dec_components_call1(TopType,
779			 [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
780			 Tpos,OptPos,MaybeComma,DecInfObj,Ext,AccTerm,AccBytes,NumberOfOptionals) ->
781    Pos = case Ext of
782	      noext -> Tpos;
783	      {ext,Epos,_Enum} -> Tpos - Epos + 1
784	  end,
785    emit(MaybeComma),
786%%    asn1ct_name:new(term),
787    InnerType =
788	case Type#type.def of
789	    #'ObjectClassFieldType'{type=InType} ->
790		InType;
791	    Def ->
792		asn1ct_gen:get_inner(Def)
793	end,
794% 	case asn1ct_gen:get_constraint(Type#type.constraint,
795% 				       tableconstraint_info) of
796% 	    no ->
797% 		asn1ct_gen:get_inner(Type#type.def);
798% 	    _ ->
799% 		Type#type.def
800% 	end,
801    case InnerType of
802	#'Externaltypereference'{type=T} ->
803	    emit({nl,"%%  attribute number ",Tpos," with type ",
804		  T,nl});
805	IT when tuple(IT) ->
806	    emit({nl,"%%  attribute number ",Tpos," with type ",
807		  element(2,IT),nl});
808	_ ->
809	    emit({nl,"%% attribute number ",Tpos," with type ",
810		  InnerType,nl})
811    end,
812
813    case InnerType of
814	{typefield,_} ->
815	    asn1ct_name:new(term),
816	    asn1ct_name:new(tmpterm),
817	    emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
818	{objectfield,_,_} ->
819	    asn1ct_name:new(term),
820	    asn1ct_name:new(tmpterm),
821	    emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
822	_ ->
823	    asn1ct_name:new(term),
824	    emit({"{",{curr,term},",",{next,bytes},"} = "})
825    end,
826
827    NewOptPos =
828	case {Ext,Prop} of
829	    {noext,mandatory} -> OptPos; % generate nothing
830	    {noext,_} ->
831		Element = io_lib:format("Opt band (1 bsl ~w)",[NumberOfOptionals - OptPos]),
832		emit({"case ",Element," of",nl}),
833		emit({"_Opt",OptPos," when _Opt",OptPos," > 0 ->"}),
834		OptPos+1;
835	    _ ->
836		emit(["case Extensions of",nl]),
837		emit(["_ when size(Extensions) >= ",Pos,",element(",Pos,",Extensions) == 1 ->",nl])
838	end,
839    put(component_type,{true,C}),
840    {TermVar,BytesVar} = gen_dec_line(TopType,Cname,Type,Tpos,DecInfObj,Ext),
841    erase(component_type),
842    case {Ext,Prop} of
843	{noext,mandatory} -> true; % generate nothing
844	{noext,_} ->
845	    emit([";",nl,"0 ->"]),
846	    gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext);
847	_ ->
848	    emit([";",nl,"_  ->",nl]),
849	    gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext)
850    end,
851    case {Ext,Prop} of
852	{noext,mandatory} -> true; % generate nothing
853	{noext,_} ->
854	    emit([nl,"end"]);
855	_ ->
856	    emit([nl,"end"])
857
858    end,
859    asn1ct_name:new(bytes),
860    case Rest of
861	[] ->
862	    {Pos+1,AccTerm++TermVar,AccBytes++BytesVar};
863	_ ->
864	    emit({com,nl}),
865	    gen_dec_components_call1(TopType,Rest,Tpos+1,NewOptPos,"",DecInfObj,Ext,
866				     AccTerm++TermVar,AccBytes++BytesVar,NumberOfOptionals)
867    end;
868
869gen_dec_components_call1(_TopType,[],Pos,_OptPos,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
870    {Pos,AccTerm,AccBytes}.
871
872
873%%gen_dec_component_no_val(TopType,Cname,Type,_,Pos,{ext,Ep,Enum}) when Pos >= Ep ->
874%%    emit({"{asn1_NOEXTVALUE,",{curr,bytes},"}",nl});
875gen_dec_component_no_val(_,_,_,{'DEFAULT',DefVal},_,_) ->
876    emit(["{",{asis,DefVal},",",{curr,bytes},"}",nl]);
877gen_dec_component_no_val(_,_,_,'OPTIONAL',_,_) ->
878    emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl});
879gen_dec_component_no_val(_,_,_,mandatory,_,{ext,_,_}) ->
880    emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl}).
881
882
883gen_dec_line(TopType,Cname,Type,Pos,DecInfObj,Ext)  ->
884    Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
885					  asn1ct_gen:rt2ct_suffix()])),
886    Atype =
887	case Type of
888	    #type{def=#'ObjectClassFieldType'{type=InnerType}} ->
889		InnerType;
890	    _  ->
891		asn1ct_gen:get_inner(Type#type.def)
892	end,
893% 	case asn1ct_gen:get_constraint(Type#type.constraint,
894% 				       tableconstraint_info) of
895% 	    no ->
896% 		asn1ct_gen:get_inner(Type#type.def);
897% 	    _ ->
898% 		Type#type.def
899% 	end,
900    BytesVar0 = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
901    BytesVar = case Ext of
902		   {ext,Ep,_} when Pos >= Ep ->
903		       emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,
904			     "}=?RT_PER:decode_open_type(",
905			     {curr,bytes},",[]),",nl,
906			     "{TmpValx",Pos,",_}="]),
907		       io_lib:format("TmpVal~p",[Pos]);
908		   _ -> BytesVar0
909	       end,
910    SaveBytes =
911	case Atype of
912	    {typefield,_} ->
913		case DecInfObj of
914		    false -> % This is in a choice with typefield components
915			{Name,RestFieldNames} =
916			    (Type#type.def)#'ObjectClassFieldType'.fieldname,
917% 			    asn1ct_gen:get_constraint(Type#type.constraint,
918% 						      tableconstraint_info),
919			asn1ct_name:new(tmpterm),
920			asn1ct_name:new(reason),
921			emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
922			      "} = ?RT_PER:decode_open_type(",{curr,bytes},
923			      ", []),",nl]),
924			emit([indent(2),"case (catch ObjFun(",
925			      {asis,Name},
926			      ",",{curr,tmpterm},",telltype,",
927			      {asis,RestFieldNames},")) of", nl]),
928			emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
929			emit([indent(6),"exit({'Type not ",
930			      "compatible with table constraint', ",
931			      {curr,reason},"});",nl]),
932			asn1ct_name:new(tmpterm),
933			emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
934			emit([indent(6),"{",Cname,", {",{curr,tmpterm},", ",
935			      {next,bytes},"}}",nl]),
936			emit([indent(2),"end"]),
937			[];
938		    {"got objfun through args","ObjFun"} ->
939			%% this is when the generated code gots the
940			%% objfun though arguments on function
941			%% invocation.
942			{Name,RestFieldNames} =
943			    (Type#type.def)#'ObjectClassFieldType'.fieldname,
944			emit(["?RT_PER:decode_open_type(",{curr,bytes},
945			      ", []),",nl]),
946			emit([{curr,term}," =",nl,
947			      "  case (catch ObjFun(",{asis,Name},",",
948			      {curr,tmpterm},",telltype,",
949			      {asis,RestFieldNames},")) of", nl]),
950			emit(["    {'EXIT',",{curr,reason},"} ->",nl]),
951			emit([indent(6),"exit({'Type not ",
952			      "compatible with table constraint', ",
953			      {curr,reason},"});",nl]),
954			asn1ct_name:new(tmpterm),
955			emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
956			emit([indent(6),{curr,tmpterm},nl]),
957			emit([indent(2),"end"]),
958			[];
959		    _ ->
960			emit({"?RT_PER:decode_open_type(",{curr,bytes},
961			      ", [])"}),
962			RefedFieldName =
963			    (Type#type.def)#'ObjectClassFieldType'.fieldname,
964% 			    asn1ct_gen:get_constraint(Type#type.constraint,
965% 						      tableconstraint_info),
966			[{Cname,RefedFieldName,
967			  asn1ct_gen:mk_var(asn1ct_name:curr(term)),
968			  asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
969			  get_components_prop()}]
970		end;
971	    {objectfield,PrimFieldName1,PFNList} ->
972		emit({"?RT_PER:decode_open_type(",{curr,bytes},", [])"}),
973		[{Cname,{PrimFieldName1,PFNList},
974		  asn1ct_gen:mk_var(asn1ct_name:curr(term)),
975		  asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
976		  get_components_prop()}];
977	    _ ->
978		CurrMod = get(currmod),
979		case asn1ct_gen:type(Atype) of
980		    #'Externaltypereference'{module=CurrMod,type=EType} ->
981			emit({"'dec_",EType,"'(",BytesVar,",telltype)"});
982		    #'Externaltypereference'{module=Mod,type=EType} ->
983			emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
984			      ",telltype)"});
985		    {primitive,bif} ->
986			case Atype of
987			   {fixedtypevaluefield,_,Btype} ->
988				Ctgenmod:gen_dec_prim(per,Btype,
989						      BytesVar);
990			    _ ->
991				Ctgenmod:gen_dec_prim(per,Type,
992						      BytesVar)
993			end;
994		    'ASN1_OPEN_TYPE' ->
995			case Type#type.def of
996			    #'ObjectClassFieldType'{type=OpenType} ->
997				Ctgenmod:gen_dec_prim(per,#type{def=OpenType},
998						      BytesVar);
999			    _ ->
1000				Ctgenmod:gen_dec_prim(per,Type,
1001						      BytesVar)
1002			end;
1003		    #typereference{val=Dname} ->
1004			emit({"'dec_",Dname,"'(",BytesVar,",telltype)"});
1005		    {notype,_} ->
1006			emit({"'dec_",Atype,"'(",BytesVar,",telltype)"});
1007		    {constructed,bif} ->
1008			NewTypename = [Cname|TopType],
1009			case Type#type.tablecinf of
1010			    [{objfun,_}|_R] ->
1011				emit({"'dec_",asn1ct_gen:list2name(NewTypename),
1012				      "'(",BytesVar,", telltype, ObjFun)"});
1013			    _ ->
1014				emit({"'dec_",asn1ct_gen:list2name(NewTypename),
1015				      "'(",BytesVar,", telltype)"})
1016			end
1017		end,
1018		case DecInfObj of
1019		    {Cname,{_,OSet,UniqueFName,ValIndex}} ->
1020			Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1021			ValueMatch = value_match(ValIndex,Term),
1022			emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
1023			      {asis,UniqueFName},", ",ValueMatch,")"});
1024		    _ ->
1025			ok
1026		end,
1027		[]
1028	end,
1029    case Ext of
1030	{ext,Ep2,_} when Pos >= Ep2 ->
1031	    emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]);
1032	_ -> true
1033    end,
1034    %% Prepare return value
1035    case DecInfObj of
1036	{Cname,ObjSet} ->
1037	    {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
1038	     SaveBytes};
1039	_ ->
1040	    {[],SaveBytes}
1041    end.
1042
1043gen_enc_choice(TopType,CompList,Ext) ->
1044    gen_enc_choice_tag(CompList, [], Ext),
1045    emit({com,nl}),
1046    emit({"case element(1,Val) of",nl}),
1047    gen_enc_choice2(TopType, CompList, Ext),
1048    emit({nl,"end"}).
1049
1050gen_enc_choice_tag({C1,C2},_,_) ->
1051    N1 = get_name_list(C1),
1052    N2 = get_name_list(C2),
1053    emit(["?RT_PER:set_choice(element(1,Val),",
1054	  {asis,{N1,N2}},", ",{asis,{length(N1),length(N2)}},")"]);
1055gen_enc_choice_tag(C,_,_) ->
1056    N = get_name_list(C),
1057    emit(["?RT_PER:set_choice(element(1,Val),",
1058	  {asis,N},", ",{asis,length(N)},")"]).
1059
1060get_name_list(L) ->
1061    get_name_list(L,[]).
1062
1063get_name_list([#'ComponentType'{name=Name}|T], Acc) ->
1064    get_name_list(T,[Name|Acc]);
1065get_name_list([], Acc) ->
1066    lists:reverse(Acc).
1067
1068%gen_enc_choice_tag([H|T],Acc,Ext) when record(H,'ComponentType') ->
1069%    gen_enc_choice_tag(T,[H#'ComponentType'.name|Acc],Ext);
1070%gen_enc_choice_tag([H|T],Acc,Ext) -> % skip EXTENSIONMARK
1071%    gen_enc_choice_tag(T,Acc,Ext);
1072%gen_enc_choice_tag([],Acc,Ext) ->
1073%    Length = length(Acc),
1074%    emit({"?RT_PER:set_choice(element(1,Val),",{asis,Length},",",
1075%	  {asis,lists:reverse(Acc)},",",{asis,Ext},")"}),
1076%    Length.
1077
1078gen_enc_choice2(TopType, {L1,L2}, Ext) ->
1079    gen_enc_choice2(TopType, L1 ++ L2, 0, Ext);
1080gen_enc_choice2(TopType, L, Ext) ->
1081    gen_enc_choice2(TopType, L, 0, Ext).
1082
1083gen_enc_choice2(TopType,[H1,H2|T], Pos, Ext)
1084when record(H1,'ComponentType'), record(H2,'ComponentType') ->
1085    Cname = H1#'ComponentType'.name,
1086    Type = H1#'ComponentType'.typespec,
1087    EncObj =
1088% 	case asn1ct_gen:get_constraint(Type#type.constraint,
1089% 				       tableconstraint_info) of
1090% 	    no ->
1091% 		false;
1092% 	    _ ->
1093% 		{no_attr,"ObjFun"}
1094% 	end,
1095	case asn1ct_gen:get_constraint(Type#type.constraint,
1096				       componentrelation) of
1097	    no -> false;
1098	    _ -> {no_attr,"ObjFun"}
1099	end,
1100    emit({{asis,Cname}," ->",nl}),
1101    gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
1102    emit({";",nl}),
1103    gen_enc_choice2(TopType,[H2|T], Pos+1, Ext);
1104gen_enc_choice2(TopType,[H1|T], Pos, Ext) when record(H1,'ComponentType') ->
1105    Cname = H1#'ComponentType'.name,
1106    Type = H1#'ComponentType'.typespec,
1107    EncObj =
1108% 	case asn1ct_gen:get_constraint(Type#type.constraint,
1109% 				       tableconstraint_info) of
1110% 	    no ->
1111% 		false;
1112% 	    _ ->
1113% 		{no_attr,"ObjFun"}
1114% 	end,
1115	case asn1ct_gen:get_constraint(Type#type.constraint,
1116				       componentrelation) of
1117	    no -> false;
1118	    _ -> {no_attr,"ObjFun"}
1119	end,
1120    emit({{asis,H1#'ComponentType'.name}," ->",nl}),
1121    gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
1122    gen_enc_choice2(TopType,T, Pos+1, Ext);
1123gen_enc_choice2(_,[], _, _)  ->
1124    true.
1125
1126gen_dec_choice(TopType,CompList,{ext,Pos,NumExt}) ->
1127    emit({"{Ext,",{curr,bytes},"} = ?RT_PER:getbit(Bytes),",nl}),
1128    asn1ct_name:new(bytes),
1129    gen_dec_choice1(TopType,CompList,{ext,Pos,NumExt});
1130gen_dec_choice(TopType,CompList,noext) ->
1131    gen_dec_choice1(TopType,CompList,noext).
1132
1133gen_dec_choice1(TopType,CompList,noext) ->
1134    emit({"{Choice,",{curr,bytes},
1135	  "} = ?RT_PER:getchoice(",{prev,bytes},",",
1136	  length(CompList),", 0),",nl}),
1137    emit({"{Cname,{Val,NewBytes}} = case Choice of",nl}),
1138    gen_dec_choice2(TopType,CompList,noext),
1139    emit({nl,"end,",nl}),
1140    emit({nl,"{{Cname,Val},NewBytes}"});
1141gen_dec_choice1(TopType,{RootList,ExtList},Ext) ->
1142    NewList = RootList ++ ExtList,
1143    gen_dec_choice1(TopType, NewList, Ext);
1144gen_dec_choice1(TopType,CompList,{ext,ExtPos,ExtNum}) ->
1145    emit({"{Choice,",{curr,bytes},
1146	  "} = ?RT_PER:getchoice(",{prev,bytes},",",
1147	  length(CompList)-ExtNum,",Ext ),",nl}),
1148    emit({"{Cname,{Val,NewBytes}} = case Choice + Ext*",ExtPos-1," of",nl}),
1149    gen_dec_choice2(TopType,CompList,{ext,ExtPos,ExtNum}),
1150    emit([";",nl,"_ -> {asn1_ExtAlt, ?RT_PER:decode_open_type(",{curr,bytes},",[])}"]),
1151    emit({nl,"end,",nl}),
1152    emit({nl,"{{Cname,Val},NewBytes}"}).
1153
1154
1155gen_dec_choice2(TopType,L,Ext) ->
1156    gen_dec_choice2(TopType,L,0,Ext).
1157
1158gen_dec_choice2(TopType,[H1,H2|T],Pos,Ext)
1159when record(H1,'ComponentType'), record(H2,'ComponentType') ->
1160    Cname = H1#'ComponentType'.name,
1161    Type = H1#'ComponentType'.typespec,
1162    case Type#type.def of
1163	#'ObjectClassFieldType'{type={typefield,_}} ->
1164	    emit({Pos," -> ",nl}),
1165	    wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
1166	    emit({";",nl});
1167	_ ->
1168	    emit({Pos," -> {",{asis,Cname},",",nl}),
1169	    wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
1170	    emit({"};",nl})
1171    end,
1172    gen_dec_choice2(TopType,[H2|T],Pos+1,Ext);
1173gen_dec_choice2(TopType,[H1,_H2|T],Pos,Ext) when record(H1,'ComponentType') ->
1174    gen_dec_choice2(TopType,[H1|T],Pos,Ext); % skip extensionmark
1175gen_dec_choice2(TopType,[H1|T],Pos,Ext) when record(H1,'ComponentType') ->
1176    Cname = H1#'ComponentType'.name,
1177    Type = H1#'ComponentType'.typespec,
1178    case Type#type.def of
1179	#'ObjectClassFieldType'{type={typefield,_}} ->
1180	    emit({Pos," -> ",nl}),
1181	    wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext);
1182	_ ->
1183	    emit({Pos," -> {",{asis,Cname},",",nl}),
1184	    wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
1185	    emit("}")
1186    end,
1187    gen_dec_choice2(TopType,[T],Pos+1);
1188gen_dec_choice2(TopType,[_|T],Pos,Ext) ->
1189    gen_dec_choice2(TopType,T,Pos,Ext);% skip extensionmark
1190gen_dec_choice2(_,[],Pos,_)  ->
1191    Pos.
1192
1193indent(N) ->
1194    lists:duplicate(N,32). % 32 = space
1195
1196gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) ->
1197%    put(component_type,true), % add more info in component_type
1198    CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value).
1199%    erase(component_type).
1200
1201make_element(I,Val,Cname) ->
1202    case lists:member(optimize,get(encoding_options)) of
1203	false ->
1204	    io_lib:format("?RT_PER:cindex(~w,~s,~w)",[I,Val,Cname]);
1205	_ ->
1206	    io_lib:format("element(~w,~s)",[I,Val])
1207    end.
1208
1209wrap_gen_dec_line(C,TopType,Cname,Type,Pos,DIO,Ext) ->
1210    put(component_type,{true,C}),
1211    gen_dec_line(TopType,Cname,Type,Pos,DIO,Ext),
1212    erase(component_type).
1213
1214get_components_prop() ->
1215    case get(component_type) of
1216	undefined ->
1217	    mandatory;
1218	{true,#'ComponentType'{prop=Prop}} -> Prop
1219    end.
1220
1221
1222value_match(Index,Value) when atom(Value) ->
1223    value_match(Index,atom_to_list(Value));
1224value_match([],Value) ->
1225    Value;
1226value_match([{VI,_}|VIs],Value) ->
1227    value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
1228value_match1(Value,[],Acc,Depth) ->
1229    Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
1230value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
1231    value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
1232
1233notice_value_match() ->
1234    Module = get(currmod),
1235    put(value_match,{true,Module}).
1236