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_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
18-module(asn1ct_constructed_ber_bin_v2).
19
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]).
28
29
30-include("asn1_records.hrl").
31
32-import(asn1ct_gen, [emit/1,demit/1]).
33-import(asn1ct_constructed_ber,[match_tag/2]).
34
35-define(ASN1CT_GEN_BER,asn1ct_gen_ber_bin_v2).
36
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).
42
43% primitive or constructed encoding % bit 6
44-define(PRIMITIVE,   0).
45-define(CONSTRUCTED, 2#00100000).
46
47
48
49
50%%===============================================================================
51%%===============================================================================
52%%===============================================================================
53%%  Encode/decode SEQUENCE (and SET)
54%%===============================================================================
55%%===============================================================================
56%%===============================================================================
57
58gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
59    asn1ct_name:start(),
60    asn1ct_name:new(term),
61    asn1ct_name:new(bytes),
62
63    %% if EXTERNAL type the input value must be transformed to
64    %% ASN1 1990 format
65    ValName =
66	case Typename of
67	    ['EXTERNAL'] ->
68		emit([indent(4),
69		      "NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
70		      nl]),
71		"NewVal";
72	    _ ->
73	    "Val"
74	end,
75
76    {SeqOrSet,TableConsInfo,CompList} =
77	case D#type.def of
78	    #'SEQUENCE'{tablecinf=TCI,components=CL} ->
79		{'SEQUENCE',TCI,CL};
80	    #'SET'{tablecinf=TCI,components=CL} ->
81		{'SET',TCI,CL}
82	end,
83    Ext = extensible(CompList),
84    CompList1 = case CompList of
85		    {Rl,El} -> Rl ++ El;
86		    _ -> CompList
87		end,
88
89%% don't match recordname for now, because of compatibility reasons
90%%    emit(["{'",asn1ct_gen:list2rname(Typename),"'"]),
91    emit(["{_"]),
92    case length(CompList1) of
93	0 ->
94	    true;
95	CompListLen ->
96	    emit([","]),
97	    mkcindexlist([Tc || Tc <- lists:seq(1,CompListLen)])
98    end,
99    emit(["} = ",ValName,",",nl]),
100    EncObj =
101	case TableConsInfo of
102	    #simpletableattributes{usedclassfield=Used,
103				   uniqueclassfield=Unique} when Used /= Unique ->
104		false;
105	    %% ObjectSet, name of the object set in constraints
106	    %%
107	    #simpletableattributes{objectsetname=ObjectSet,
108				   c_name=AttrN,
109				   c_index=N,
110				   usedclassfield=UniqueFieldName,
111				   uniqueclassfield=UniqueFieldName,
112				   valueindex=ValueIndex} -> %% N is index of attribute that determines constraint
113		OSDef =
114		    case ObjectSet of
115			{Module,OSName} ->
116			    asn1_db:dbget(Module,OSName);
117			OSName ->
118			    asn1_db:dbget(get(currmod),OSName)
119		    end,
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
123		    true ->
124			ObjectEncode =
125			    asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
126								   AttrN])),
127			emit([ObjectEncode," = ",nl]),
128			emit(["   'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
129			      ", ",nl]),
130			ValueMatch = value_match(ValueIndex,
131						 lists:concat(["Cindex",N])),
132			emit([indent(35),ValueMatch,"),",nl]),
133			{AttrN,ObjectEncode};
134		    _ ->
135			false
136		end;
137	    _ ->
138		case D#type.tablecinf of
139		    [{objfun,_}|_] ->
140			%% when the simpletableattributes was at an outer
141			%% level and the objfun has been passed through the
142			%% function call
143			{"got objfun through args","ObjFun"};
144		    _ ->
145			false
146		end
147	end,
148
149    gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
150
151    emit([nl,"   BytesSoFar = "]),
152    case SeqOrSet of
153	'SET' when (D#type.def)#'SET'.sorted == dynamic ->
154	    emit("?RT_BER:dynamicsort_SET_components(["),
155	    mkvlist(asn1ct_name:all(encBytes)),
156	    emit(["]),",nl]);
157	_ ->
158	    emit("["),
159	    mkvlist(asn1ct_name:all(encBytes)),
160	    emit(["],",nl])
161    end,
162    emit("LenSoFar = "),
163    case asn1ct_name:all(encLen) of
164	[] -> emit("0");
165	AllLengths ->
166	    mkvplus(AllLengths)
167    end,
168    emit([",",nl]),
169    emit(["?RT_BER:encode_tags(TagIn, BytesSoFar, LenSoFar)."
170	  ,nl]).
171
172gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
173    asn1ct_name:start(),
174    asn1ct_name:new(tag),
175    #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
176    Ext = extensible(CList),
177    CompList = case CList of
178		   {Rl,El}  -> Rl ++ El;
179		   _ -> CList
180	       end,
181
182    emit(["   %%-------------------------------------------------",nl]),
183    emit(["   %% decode tag and length ",nl]),
184    emit(["   %%-------------------------------------------------",nl]),
185
186    asn1ct_name:new(tlv),
187    case CompList of
188	EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
189	    true;
190	_ ->
191	    emit([{curr,tlv}," = "])
192    end,
193    emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
194    asn1ct_name:new(tlv),
195    asn1ct_name:new(v),
196
197    {DecObjInf,UniqueFName,ValueIndex} =
198	case TableConsInfo of
199	    #simpletableattributes{objectsetname=ObjectSet,
200				   c_name=AttrN,
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;
208				_ -> false
209			    end
210		    end,
211		case lists:any(F,CompList) of
212		    true -> % when component relation constraint establish
213			%% relation from a component to another components
214			%% subtype component
215			{{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
216			 UniqueFieldName,ValIndex};
217		    false ->
218			{{AttrN,ObjectSet},UniqueFieldName,ValIndex}
219		end;
220	    _ ->
221% 		case D#type.tablecinf of
222% 		    [{objfun,_}|_] ->
223% 			{{"got objfun through args","ObjFun"},false,false};
224% 		    _ ->
225		{false,false,false}
226%	end
227	end,
228    case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
229	no_terms -> % an empty sequence
230	    emit([nl,nl]),
231	    demit(["Result = "]), %dbg
232	    %% return value as record
233	    asn1ct_name:new(rb),
234	    emit(["   {'",asn1ct_gen:list2rname(Typename),"'}.",nl,nl]);
235	{LeadingAttrTerm,PostponedDecArgs} ->
236	    emit([com,nl,nl]),
237	    case {LeadingAttrTerm,PostponedDecArgs} of
238		{[],[]} ->
239		    ok;
240		{_,[]} ->
241		    ok;
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)
248	    end,
249	    demit(["Result = "]), %dbg
250	    %% return value as record
251	    case Ext of
252		{ext,_,_} ->
253		    emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
254		noext ->
255		    emit(["case ",{prev,tlv}," of",nl,
256			  "[] -> true;",
257			  "_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
258			  "}}}) % extra fields not allowed",nl,
259			  "end,",nl])
260	    end,
261	    asn1ct_name:new(rb),
262	    case Typename of
263		['EXTERNAL'] ->
264		    emit(["   OldFormat={'",asn1ct_gen:list2rname(Typename),
265			  "', "]),
266		    mkvlist(asn1ct_name:all(term)),
267		    emit(["},",nl]),
268		    emit(["    asn1rt_check:transform_to_EXTERNAL1994",
269			  "(OldFormat).",nl]);
270		_ ->
271		    emit(["   {'",asn1ct_gen:list2rname(Typename),"', "]),
272		    mkvlist(asn1ct_name:all(term)),
273		    emit(["}.",nl,nl])
274	    end
275    end.
276
277gen_dec_postponed_decs(_,[]) ->
278    emit(nl);
279gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,
280				TmpTerm,_Tag,OptOrMand}|Rest]) ->
281
282    asn1ct_name:new(tmpterm),
283    asn1ct_name:new(reason),
284    asn1ct_name:new(tmptlv),
285
286    emit([Term," = ",nl]),
287    N = case OptOrMand of
288	    mandatory -> 0;
289	    'OPTIONAL' ->
290		emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
291		6;
292	    {'DEFAULT',Val} ->
293		emit_opt_or_mand_check(Val,TmpTerm),
294		6
295	end,
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]),
303
304    case OptOrMand of
305	mandatory -> emit([indent(N+3),"end,",nl]);
306	_ ->
307	    emit([indent(N+3),"end",nl,
308		  indent(3),"end,",nl])
309    end,
310    gen_dec_postponed_decs(DecObj,Rest).
311
312emit_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]).
316
317%%============================================================================
318%%  Encode/decode SET
319%%
320%%============================================================================
321
322gen_encode_set(Erules,Typename,D) when record(D,type) ->
323    gen_encode_sequence(Erules,Typename,D).
324
325gen_decode_set(Erules,Typename,D) when record(D,type) ->
326    asn1ct_name:start(),
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
332		   {Rl,El} -> Rl ++ El;
333		   _ -> TCompList
334	       end,
335
336    asn1ct_name:clear(),
337    asn1ct_name:new(tlv),
338    case CompList of
339	EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
340	    true;
341	_ ->
342	    emit([{curr,tlv}," = "])
343    end,
344    emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
345    asn1ct_name:new(v),
346
347
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;
354				_ -> false
355			    end
356		    end,
357		case lists:any(F,CompList) of
358		    true -> % when component relation constraint establish
359			%% relation from a component to another components
360			%% subtype component
361			{{AttrN,{deep,ObjectSet,UniqueFieldName}},
362			 UniqueFieldName};
363		    false ->
364			{{AttrN,ObjectSet},UniqueFieldName}
365		end;
366	    _ ->
367		{false,false}
368	end,
369
370    case CompList of
371	[] -> % empty set
372	    true;
373	_ ->
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]),
381
382	    emit(["PositionList = [SetFun(TempTlv)|| TempTlv <- ",{curr,tlv},"],",nl]),
383	    asn1ct_name:new(tlv),
384	    emit([{curr,tlv}," = [Stlv || {_,Stlv} <- lists:sort(PositionList)],",nl]),
385	    asn1ct_name:new(tlv)
386
387    end,
388    case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
389	no_terms -> % an empty sequence
390	    emit([nl,nl]),
391	    demit(["Result = "]), %dbg
392	    %% return value as record
393	    emit(["   {'",asn1ct_gen:list2rname(Typename),"'}.",nl]);
394	{LeadingAttrTerm,PostponedDecArgs} ->
395	    emit([com,nl,nl]),
396	    case {LeadingAttrTerm,PostponedDecArgs} of
397		{[],[]} ->
398		    ok;
399		{_,[]} ->
400		    ok;
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)
406	    end,
407	    demit(["Result = "]), %dbg
408	    %% return value as record
409	    case Ext of
410		{ext,_,_} ->
411		    emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
412		noext ->
413		    emit(["case ",{prev,tlv}," of",nl,
414			  "[] -> true;",
415			  "_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
416			  "}}}) % extra fields not allowed",nl,
417			  "end,",nl])
418	    end,
419	    emit(["   {'",asn1ct_gen:list2rname(Typename),"', "]),
420	    mkvlist(asn1ct_name:all(term)),
421	    emit(["}.",nl])
422    end.
423
424
425%%===============================================================================
426%%===============================================================================
427%%===============================================================================
428%%  Encode/decode SEQUENCE OF and SET OF
429%%===============================================================================
430%%===============================================================================
431%%===============================================================================
432
433gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
434    asn1ct_name:start(),
435    {SeqOrSetOf, Cont} = D#type.def,
436
437    Objfun = case D#type.tablecinf of
438		 [{objfun,_}|_R] ->
439		     ", ObjFun";
440		 _ ->
441		     ""
442	     end,
443
444    emit(["   {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
445	  "_components'(Val",Objfun,",[],0),",nl]),
446
447    emit(["   ?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl,nl]),
448
449    gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
450
451
452gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when record(D,type) ->
453    asn1ct_name:start(),
454    {SeqOrSetOf, _TypeTag, Cont} =
455	case D#type.def of
456	    {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
457	    {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
458	end,
459    TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
460
461    emit(["   %%-------------------------------------------------",nl]),
462    emit(["   %% decode tag and length ",nl]),
463    emit(["   %%-------------------------------------------------",nl]),
464
465    asn1ct_name:new(tlv),
466    emit([{curr,tlv},
467	  " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
468    asn1ct_name:new(v),
469
470    emit(["["]),
471
472    InnerType = asn1ct_gen:get_inner(Cont#type.def),
473    ContName = case asn1ct_gen:type(InnerType) of
474		   Atom when atom(Atom) -> Atom;
475		   _ -> TypeNameSuffix
476	       end,
477%% fix me
478    ObjFun =
479	case D#type.tablecinf of
480	    [{objfun,_}|_R] ->
481		", ObjFun";
482	    _ ->
483		[]
484	end,
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]).
488
489
490gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
491  when record(Cont,type)->
492
493    {Objfun,Objfun_novar,EncObj} =
494	case Cont#type.tablecinf of
495	    [{objfun,_}|_R] ->
496		{", ObjFun",", _",{no_attr,"ObjFun"}};
497	    _ ->
498		{"","",false}
499	end,
500    emit(["'enc_",asn1ct_gen:list2name(Typename),
501	  "_components'([]",Objfun_novar,", AccBytes, AccLen) -> ",nl]),
502
503    case catch lists:member(der,get(encoding_options)) of
504	true ->
505	    emit([indent(3),
506		  "{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
507	_ ->
508	    emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
509    end,
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),
515    emit([",",nl]),
516    emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
517	  "_components'(T",Objfun,","]),
518    emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
519
520%%============================================================================
521%%  Encode/decode CHOICE
522%%
523%%============================================================================
524
525gen_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
530		    {Rl,El} -> Rl ++ El;
531		    _ -> CompList
532		end,
533    gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
534    emit([nl,nl]).
535
536gen_decode_choice(Erules,Typename,D) when record(D,type) ->
537    asn1ct_name:start(),
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
543		    {Rl,El} -> Rl ++ El;
544		    _ -> CompList
545		end,
546    gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
547    emit([".",nl]).
548
549
550%%============================================================================
551%%  Encode SEQUENCE
552%%
553%%============================================================================
554
555gen_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),
558    Element =
559	case TopType of
560	    ['EXTERNAL'] ->
561		io_lib:format("Cindex~w",[Pos]);
562	    _ ->
563		io_lib:format("Cindex~w",[Pos])
564	end,
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),
568    emit([com,nl]),
569    gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj);
570
571gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
572	true.
573
574%%============================================================================
575%%  Decode SEQUENCE
576%%
577%%============================================================================
578
579gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
580    gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
581
582
583gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
584    {LA,PostponedDec} =
585	gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
586			  Ext,DecObjInf),
587    case Rest of
588	[] ->
589	    {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
590	_ ->
591	    emit([com,nl]),
592	    asn1ct_name:new(bytes),
593	    gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
594				   LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
595    end;
596
597gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
598    no_terms.
599
600
601%%----------------------------
602%%SEQUENCE mandatory
603%%----------------------------
604
605gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
606    InnerType =
607	case Type#type.def of
608	    #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
609	    _ -> asn1ct_gen:get_inner(Type#type.def)
610	end,
611% 	case asn1ct_gen:get_constraint(Type#type.constraint,
612% 				       tableconstraint_info) of
613% 	    no ->
614% 		asn1ct_gen:get_inner(Type#type.def);
615% 	    _ ->
616% 		Type#type.def
617% 	end,
618    Prop1 = case {Prop,Ext} of
619		{mandatory,{ext,Epos,_}} when Pos >= Epos ->
620		    'OPTIONAL';
621		_ ->
622		    Prop
623	    end,
624    print_attribute_comment(InnerType,Pos,Cname,Prop1),
625    asn1ct_name:new(term),
626    emit_term_tlv(Prop1,InnerType,DecObjInf),
627    asn1ct_name:new(rb),
628    PostponedDec =
629	gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
630    asn1ct_name:new(v),
631    asn1ct_name:new(tlv),
632    asn1ct_name:new(form),
633    PostponedDec.
634
635
636emit_term_tlv({'DEFAULT',_},InnerType,DecObjInf) ->
637    emit_term_tlv(opt_or_def,InnerType,DecObjInf);
638emit_term_tlv('OPTIONAL',InnerType,DecObjInf) ->
639    emit_term_tlv(opt_or_def,InnerType,DecObjInf);
640emit_term_tlv(Prop,{typefield,_},DecObjInf) ->
641    emit_term_tlv(Prop,type_or_object_field,DecObjInf);
642emit_term_tlv(Prop,{objectfield,_,_},DecObjInf) ->
643    emit_term_tlv(Prop,type_or_object_field,DecObjInf);
644emit_term_tlv(opt_or_def,type_or_object_field,_) ->
645    asn1ct_name:new(tmpterm),
646    emit(["{",{curr,tmpterm},",",{curr,tlv},"} = "]);
647emit_term_tlv(opt_or_def,_,_) ->
648    emit(["{",{curr,term},",",{curr,tlv},"} = "]);
649emit_term_tlv(_,type_or_object_field,false) ->
650     emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
651	  {curr,term}," = "]);
652emit_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}," = "]);
656emit_term_tlv(mandatory,_,_) ->
657    emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
658	  {curr,term}," = "]).
659
660
661gen_dec_set_cases(_Erules,_TopType,[],Pos) ->
662    Pos;
663gen_dec_set_cases(Erules,TopType,[Comp|RestComps],Pos) ->
664    Name = Comp#'ComponentType'.name,
665    Type = Comp#'ComponentType'.typespec,
666    CTags = Comp#'ComponentType'.tags,
667
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];
673               [FirstTag|_] ->
674		   [(?ASN1CT_GEN_BER:decode_class(FirstTag#tag.class) bsl 10) + FirstTag#tag.number]
675	   end,
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];
681				      _ -> ""
682				  end,
683		      emit(["TTlv = {",H,",_} ->",nl]),
684		      emit([indent(4),"{",Pos,", TTlv}",Semicolon]),
685		      Fun(T,Fun,N+1);
686		 ([],_,0) ->
687		      true;
688		 ([],_,_) ->
689		      emit([";",nl])
690	      end,
691    CaseFun(Tags,CaseFun,0),
692%%    emit([";",nl]),
693    gen_dec_set_cases(Erules,TopType,RestComps,Pos+1).
694
695
696
697%%---------------------------------------------
698%%  Encode CHOICE
699%%---------------------------------------------
700%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
701
702
703gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
704    gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
705
706gen_enc_choice1(Erules,TopType,_Tag,CompList,_Ext) ->
707    asn1ct_name:clear(),
708    emit(["   {EncBytes,EncLen} = case element(1,Val) of",nl]),
709    gen_enc_choice2(Erules,TopType,CompList),
710    emit([nl,"   end,",nl,nl]),
711
712    emit(["?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl]).
713
714
715gen_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]),
719    {Encobj,Assign} =
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};
728	    _ ->
729		{false,[]}
730	end,
731% 	case asn1ct_gen:get_constraint(Type#type.constraint,
732% 				       tableconstraint_info) of
733% 	    no ->
734% 		{false,[]};
735% 	    _ ->
736% 		asn1ct_name:new(tmpBytes),
737% 		asn1ct_name:new(encBytes),
738% 		asn1ct_name:new(encLen),
739% 		Emit = ["{",{curr,tmpBytes},", _} = "],
740% 		{{no_attr,"ObjFun"},Emit}
741% 	end,
742    gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
743		 mandatory,Assign,Encobj),
744    case Encobj of
745	false -> ok;
746	_ ->
747	    emit([",",nl,indent(9),"{",{curr,encBytes},", ",
748		  {curr,encLen},"}"])
749    end,
750    emit([";",nl]),
751    case T of
752	[] ->
753	    emit([indent(6), "Else -> ",nl,
754		  indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
755	_ ->
756	    true
757    end,
758    gen_enc_choice2(Erules,TopType,T);
759
760gen_enc_choice2(_Erules,_TopType,[])  ->
761    true.
762
763
764
765
766%%--------------------------------------------
767%%  Decode CHOICE
768%%--------------------------------------------
769
770gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
771    asn1ct_name:clear(),
772    asn1ct_name:new(tlv),
773    emit([{curr,tlv},
774	  " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
775    asn1ct_name:new(tlv),
776    asn1ct_name:new(v),
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]),
785    case Ext of
786	noext ->
787	    emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
788		  {curr,else},"}}})",nl]);
789	_ ->
790	    emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},")}",nl])
791    end,
792    emit([indent(3),"end",nl]),
793    asn1ct_name:new(tag),
794    asn1ct_name:new(else).
795
796
797gen_dec_choice_cases(_Erules,_TopType, []) ->
798    ok;
799gen_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),
810		      emit(["};",nl,nl]),
811		      Fun(Tail,Fun);
812		 ([],_) ->
813		      ok
814	      end,
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) +
821		FirstT#tag.number,
822	    asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
823					     [DecTag],Type}),
824	    asn1ct:update_gen_state(namelist,Names),
825	    emit([indent(4),{curr,res}," = ",
826		  match_tag(ber_bin,{FirstT#tag.class,FirstT#tag.number}),
827		  " -> ",nl]),
828	    emit([indent(8),"{",{asis,Cname},", {'",
829		  asn1ct_gen:list2name([Cname|TopType]),"',",
830		  {curr,res},"}};",nl,nl]);
831	{[FirstT|RestT],_} ->
832	    emit([indent(4),"{",
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),
837	    emit(["};",nl,nl])
838    end,
839    gen_dec_choice_cases(Erules,TopType, T).
840
841
842
843%%---------------------------------------
844%% Generate the encode/decode code
845%%---------------------------------------
846
847gen_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);
855gen_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).
859
860gen_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),
865			    X#tag.form,
866			    X#tag.number)
867			 || X <- Type#type.tag]),
868    InnerType = asn1ct_gen:get_inner(Type#type.def),
869    WhatKind = asn1ct_gen:type(InnerType),
870    emit(IndDeep),
871    emit(Assign),
872    gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
873		       Element),
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
883		{notype,T} ->
884		    throw({error,{notype,type_from_object,T}});
885		{Name,RestFieldNames} when atom(Name) ->
886		    case OptOrMand of
887			mandatory -> ok;
888			_ ->
889%			    emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
890			    emit(["{",{curr,tmpBytes},",_ } = "])
891%				  "} = "])
892		    end,
893		    emit([Fun,"(",{asis,Name},", ",Element,", ",
894			  {asis,RestFieldNames},"),",nl]),
895		    emit(IndDeep),
896		    case OptOrMand of
897			mandatory ->
898			    emit(["{",{curr,encBytes},",",{curr,encLen},
899				  "} = "]),
900			    emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
901				  ",",{asis,Tag},")"]);
902			_ ->
903%			    emit(["{",{next,tmpBytes},", _} = "]),
904			    emit(["{",{next,tmpBytes},",",{curr,tmpLen},
905				  "} = "]),
906			    emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
907				  ",",{asis,Tag},"),",nl]),
908			    emit(IndDeep),
909			    emit(["{",{next,tmpBytes},", ",{curr,tmpLen},"}"])
910		    end;
911		_ ->
912		    throw({asn1,{'internal error'}})
913	    end;
914	{{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
915					PFNList}},_},
916	 {componentrelation,_,_}} ->
917	    %% this is when the dotted list in the FieldName has more
918	    %% than one element
919	    {_LeadingAttrName,Fun} = EncObj,
920	    emit(["?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
921		  ", ",Element,", ",{asis,PFNList},"))"]);
922	_ ->
923	    case WhatKind of
924		{primitive,bif} ->
925		    EncType =
926			case Type#type.def of
927			    #'ObjectClassFieldType'{type={fixedtypevaluefield,_,Btype}} ->
928				Btype;
929			    _ ->
930				Type
931			end,
932		    ?ASN1CT_GEN_BER:gen_encode_prim(ber,EncType,{asis,Tag},
933						   Element);
934		{notype,_} ->
935		    emit(["'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"]);
936		'ASN1_OPEN_TYPE' ->
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);
940			_ ->
941			    ?ASN1CT_GEN_BER:gen_encode_prim(ber,Type,
942							    {asis,Tag},
943							    Element)
944		    end;
945		_ ->
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},
951				  ", ",Fun,")"]);
952			_ ->
953			    emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
954		    end
955	    end
956    end,
957    case OptOrMand of
958	mandatory -> true;
959	_ ->
960	    emit([nl,indent(7),"end"])
961    end.
962
963gen_optormand_case(mandatory,_Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
964		   _Element) ->
965    ok;
966gen_optormand_case('OPTIONAL',Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
967		   Element) ->
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)]);
972gen_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
976	true ->
977	    emit(" case catch "),
978	    asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
979				      WhatKind,{asis,DefaultValue},
980				      Element),
981	    emit([" of",nl]),
982	    emit([indent(12),"true -> {[],0};",nl]);
983	_ ->
984	    emit([" case ",Element," of",nl]),
985	    emit([indent(9),"asn1_DEFAULT -> {",
986		  empty_lb(Erules),
987		  ",0};",nl]),
988	    case DefaultValue of
989		#'Externalvaluereference'{module=CurrMod,
990					  value=V} ->
991		    emit([indent(9),"?",{asis,V}," -> {",
992			  empty_lb(Erules),",0};",nl]);
993		_ ->
994		    emit([indent(9),{asis,
995				     DefaultValue}," -> {",
996			  empty_lb(Erules),",0};",nl])
997	    end
998    end,
999    emit([indent(9),"_ ->",nl,indent(12)]).
1000
1001
1002
1003gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf)  ->
1004    BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(v)),
1005    Tag =
1006	[(?ASN1CT_GEN_BER:decode_class(X#tag.class) bsl 10) + X#tag.number ||
1007	    X <- Type#type.tag],
1008    ChoiceTags =
1009	[(?ASN1CT_GEN_BER:decode_class(Class) bsl 10) + Number||
1010	    {Class,Number} <- CTags],
1011    InnerType =
1012	case Type#type.def of
1013	    #'ObjectClassFieldType'{type=OCFTType} ->
1014		OCFTType;
1015	    _ ->
1016		asn1ct_gen:get_inner(Type#type.def)
1017	end,
1018    PostpDec =
1019	case OptOrMand of
1020	    mandatory ->
1021		gen_dec_call(InnerType,Erules,TopType,Cname,Type,
1022			     BytesVar,Tag,
1023			     mandatory,", mandatory, ",DecObjInf,OptOrMand);
1024	    _ -> %optional or default or a mandatory component after an extensionmark
1025		{FirstTag,RestTag} =
1026		    case Tag of
1027			[] ->
1028			    {ChoiceTags,[]};
1029			[Ft|Rt] ->
1030			    {Ft,Rt}
1031		    end,
1032		emit(["case ",{prev,tlv}," of",nl]),
1033		PostponedDec =
1034		    case Tag of
1035			[] when length(ChoiceTags) > 0 -> % a choice without explicit tag
1036			    Fcases =
1037				fun(FirstTag1) ->
1038					emit(["[",{curr,v}," = {",{asis,FirstTag1},
1039					      ",_}|Temp",
1040					      {curr,tlv},
1041					      "] ->",nl]),
1042					emit([indent(4),"{"]),
1043					Pdec=
1044					    gen_dec_call(InnerType,Erules,
1045							 TopType,Cname,Type,
1046							 BytesVar,RestTag,
1047							 mandatory,
1048							 ", mandatory, ",
1049							 DecObjInf,OptOrMand),
1050
1051					emit([", Temp",{curr,tlv},"}"]),
1052					emit([";",nl]),
1053					Pdec
1054				end,
1055			    hd([Fcases(TmpTag)|| TmpTag <- FirstTag]);
1056
1057			[] -> % an open type without explicit tag
1058			    emit(["[",{curr,v},"|Temp",{curr,tlv},"] ->",nl]),
1059			    emit([indent(4),"{"]),
1060			    Pdec=
1061				gen_dec_call(InnerType,Erules,TopType,Cname,
1062					     Type,BytesVar,RestTag,mandatory,
1063					     ", mandatory, ",DecObjInf,
1064					     OptOrMand),
1065
1066			    emit([", Temp",{curr,tlv},"}"]),
1067			    emit([";",nl]),
1068			    Pdec;
1069
1070			_ ->
1071			    emit(["[{",{asis,FirstTag},
1072				  ",",{curr,v},"}|Temp",
1073				  {curr,tlv},
1074				  "] ->",nl]),
1075			    emit([indent(4),"{"]),
1076			    Pdec=
1077				gen_dec_call(InnerType,Erules,TopType,Cname,
1078					     Type,BytesVar,RestTag,mandatory,
1079					     ", mandatory, ",DecObjInf,
1080					     OptOrMand),
1081
1082			    emit([", Temp",{curr,tlv},"}"]),
1083			    emit([";",nl]),
1084			    Pdec
1085		    end,
1086
1087		emit([indent(4),"_ ->",nl]),
1088		case OptOrMand of
1089		    {'DEFAULT', Def} ->
1090			emit([indent(8),"{",{asis,Def},",",{prev,tlv},"}",nl]);
1091		    'OPTIONAL' ->
1092			emit([indent(8),"{ asn1_NOVALUE, ",{prev,tlv},"}",nl])
1093		end,
1094		emit(["end"]),
1095		PostponedDec
1096	end,
1097    case DecObjInf of
1098	{Cname,ObjSet} -> % this must be the component were an object is
1099	    %% chosen from the object set according to the table
1100	    %% constraint.
1101	    {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
1102	     PostpDec};
1103	_  -> {[],PostpDec}
1104    end.
1105
1106gen_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),
1112
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]),
1123
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]),
1133    [];
1134gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
1135    emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
1136    RefedFieldName =
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}];
1142gen_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}];
1146gen_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),
1151    case DecObjInf of
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,")"]);
1158	_ ->
1159	    ok
1160    end,
1161    [].
1162gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
1163	      Tag,OptOrMand,_) ->
1164    case {asn1ct:get_gen_state_field(namelist),InnerType} of
1165	{[{Cname,undecoded}|Rest],_} ->
1166	    asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
1167					     Tag,Type}),
1168	    asn1ct:update_gen_state(namelist,Rest),
1169%	    emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
1170	    emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
1171		  BytesVar,"}"]);
1172	{_,{fixedtypevaluefield,_,Btype}} ->
1173	    ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],
1174					?PRIMITIVE,OptOrMand);
1175	_ ->
1176	    ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
1177					?PRIMITIVE,OptOrMand)
1178    end;
1179gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
1180	      Tag,OptOrMand,_) ->
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,
1184					     Tag,Type}),
1185	    asn1ct:update_gen_state(namelist,Rest),
1186	    emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
1187		  BytesVar,"}"]);
1188%	    emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
1189	{_,#'ObjectClassFieldType'{type=OpenType}} ->
1190	    ?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType},
1191					 BytesVar,Tag,[],
1192					 ?PRIMITIVE,OptOrMand);
1193	_ ->
1194	    ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
1195					 ?PRIMITIVE,OptOrMand)
1196    end;
1197gen_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,
1202					     Tag,Type}),
1203	    asn1ct:update_gen_state(namelist,Rest),
1204	    emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
1205		  BytesVar,"}"]);
1206	_ ->
1207%	    {DecFunName, _DecMod, _DecFun} =
1208%		case {asn1ct:get_gen_state_field(namelist),WhatKind} of
1209	    EmitDecFunCall =
1210		fun(FuncName) ->
1211			case {WhatKind,Type#type.tablecinf} of
1212			    {{constructed,bif},[{objfun,_}|_Rest]} ->
1213				emit([FuncName,"(",BytesVar,", ",{asis,Tag},
1214				      ", ObjFun)"]);
1215			    _ ->
1216				emit([FuncName,"(",BytesVar,", ",{asis,Tag},")"])
1217			end
1218		end,
1219	    case asn1ct:get_gen_state_field(namelist) of
1220		[{Cname,List}|Rest] when list(List) ->
1221		    case WhatKind of
1222			#'Externaltypereference'{} ->
1223			    %%io:format("gen_dec_call1 1:~n~p~n~n",[WhatKind]),
1224			    asn1ct:add_tobe_refed_func({WhatKind,List});
1225			_ ->
1226			    %%io:format("gen_dec_call1 2:~n~p~n~n",[[Cname|TopType]]),
1227			    asn1ct:add_tobe_refed_func({[Cname|TopType],
1228							List})
1229		    end,
1230		    asn1ct:update_gen_state(namelist,Rest),
1231		    Prefix=asn1ct:get_gen_state_field(prefix),
1232		    {DecFunName,_,_}=
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],
1242						     parts,
1243						     [],Type}),
1244		    emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',"]),
1245		    EmitDecFunCall("?RT_BER:match_tags"),
1246		    emit("}");
1247		_ ->
1248		    {DecFunName,_,_}=
1249			mkfuncname(TopType,Cname,WhatKind,"dec_"),
1250		    EmitDecFunCall(DecFunName)
1251	    end
1252% 	    case {WhatKind,Type#type.tablecinf} of
1253% 		{{constructed,bif},[{objfun,_}|_Rest]} ->
1254% 		    emit([DecFunName,"(",BytesVar,", ",{asis,Tag},
1255% 			  ", ObjFun)"]);
1256% 		_ ->
1257% 		    emit([DecFunName,"(",BytesVar,", ",{asis,Tag},")"])
1258% 	    end
1259    end.
1260
1261
1262%%------------------------------------------------------
1263%% General and special help functions (not exported)
1264%%------------------------------------------------------
1265
1266
1267indent(N) ->
1268    lists:duplicate(N,32). % 32 = space
1269
1270mkcindexlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
1271    emit(["Cindex",H,Sep]),
1272    mkcindexlist([T1|T], Sep);
1273mkcindexlist([H|T], Sep) ->
1274    emit(["Cindex",H]),
1275    mkcindexlist(T, Sep);
1276mkcindexlist([], _) ->
1277    true.
1278
1279mkcindexlist(L) ->
1280    mkcindexlist(L,", ").
1281
1282
1283mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
1284    emit([{var,H},Sep]),
1285    mkvlist([T1|T], Sep);
1286mkvlist([H|T], Sep) ->
1287    emit([{var,H}]),
1288    mkvlist(T, Sep);
1289mkvlist([], _) ->
1290    true.
1291
1292mkvlist(L) ->
1293    mkvlist(L,", ").
1294
1295mkvplus(L) ->
1296    mkvlist(L," + ").
1297
1298extensible(CompList) when list(CompList) ->
1299    noext;
1300extensible({RootList,ExtList}) ->
1301    {ext,length(RootList)+1,length(ExtList)}.
1302
1303
1304print_attribute_comment(InnerType,Pos,Cname,Prop) ->
1305    CommentLine = "%%-------------------------------------------------",
1306    emit([nl,CommentLine]),
1307    case InnerType of
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]);
1312	_ ->
1313	    emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",InnerType])
1314    end,
1315    case Prop of
1316	mandatory ->
1317	    continue;
1318	{'DEFAULT', Def} ->
1319	    emit([" DEFAULT = ",{asis,Def}]);
1320	'OPTIONAL' ->
1321	    emit([" OPTIONAL"])
1322    end,
1323    emit([nl,CommentLine,nl]).
1324
1325
1326
1327mkfuncname(TopType,Cname,WhatKind,Prefix) ->
1328    CurrMod = get(currmod),
1329    case WhatKind of
1330	#'Externaltypereference'{module=CurrMod,type=EType} ->
1331	    F = lists:concat(["'",Prefix,EType,"'"]),
1332	    {F, "?MODULE", F};
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]),"'"]),
1338	    {F, "?MODULE", F}
1339    end.
1340
1341empty_lb(ber) ->
1342    "[]";
1343empty_lb(ber_bin) ->
1344    "<<>>";
1345empty_lb(ber_bin_v2) ->
1346    "<<>>".
1347
1348value_match(Index,Value) when atom(Value) ->
1349    value_match(Index,atom_to_list(Value));
1350value_match([],Value) ->
1351    Value;
1352value_match([{VI,_}|VIs],Value) ->
1353    value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
1354value_match1(Value,[],Acc,Depth) ->
1355    Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
1356value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
1357    value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
1358