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.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
18-module(asn1ct_constructed_ber).
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%%%% Application internal exports
30-export([match_tag/2]).
31
32-include("asn1_records.hrl").
33
34-import(asn1ct_gen, [emit/1,demit/1]).
35
36% the encoding of class of tag bits 8 and 7
37-define(UNIVERSAL,   0).
38-define(APPLICATION, 16#40).
39-define(CONTEXT,     16#80).
40-define(PRIVATE,     16#C0).
41
42% primitive or constructed encoding % bit 6
43-define(PRIMITIVE,   0).
44-define(CONSTRUCTED, 2#00100000).
45
46
47
48
49%%===============================================================================
50%%===============================================================================
51%%===============================================================================
52%%  Encode/decode SEQUENCE
53%%===============================================================================
54%%===============================================================================
55%%===============================================================================
56
57gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
58    asn1ct_name:start(),
59    asn1ct_name:new(term),
60    asn1ct_name:new(bytes),
61
62    %% if EXTERNAL type the input value must be transformed to
63    %% ASN1 1990 format
64    case Typename of
65	['EXTERNAL'] ->
66	    emit(["   NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
67		  nl]);
68	_ ->
69	    ok
70    end,
71
72    {SeqOrSet,TableConsInfo,CompList} =
73	case D#type.def of
74	    #'SEQUENCE'{tablecinf=TCI,components=CL} ->
75		{'SEQUENCE',TCI,CL};
76	    #'SET'{tablecinf=TCI,components=CL} ->
77		{'SET',TCI,CL}
78	end,
79    Ext = extensible(CompList),
80    CompList1 = case CompList of
81		    {Rl,El} -> Rl ++ El;
82		    _ -> CompList
83		end,
84    EncObj =
85	case TableConsInfo of
86	    #simpletableattributes{usedclassfield=Used,
87				   uniqueclassfield=Unique} when Used /= Unique ->
88		false;
89	    %% ObjectSet, name of the object set in constraints
90	    %%
91	    %%{ObjectSet,AttrN,N,UniqueFieldName}
92	    #simpletableattributes{objectsetname=ObjectSet,
93				   c_name=AttrN,
94				   c_index=N,
95				   usedclassfield=UniqueFieldName,
96				   uniqueclassfield=UniqueFieldName,
97				   valueindex=ValueIndex
98				  } ->
99		OSDef =
100		    case ObjectSet of
101			{Module,OSName} ->
102			    asn1_db:dbget(Module,OSName);
103			OSName ->
104			    asn1_db:dbget(get(currmod),OSName)
105		    end,
106%		io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
107%			  [get(currmod),OSName,AttrN,N,UniqueFieldName]),
108		case (OSDef#typedef.typespec)#'ObjectSet'.gen of
109		    true ->
110% 			Val = lists:concat(["?RT_BER:cindex(",
111% 					    N+1,",Val,"]),
112			ObjectEncode =
113			    asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
114								   AttrN])),
115			emit({ObjectEncode," = ",nl}),
116			emit({"  'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
117			      ", ",nl}),
118%			emit({indent(35),"?RT_BER:cindex(",N+1,", Val,",
119%			      {asis,AttrN},")),",nl}),
120			emit([indent(10+length(atom_to_list(ObjectSet))),
121			      "value_match(",{asis,ValueIndex},",",
122			      "?RT_BER:cindex(",N+1,",Val,",
123			      {asis,AttrN},"))),",nl]),
124			notice_value_match(),
125			{AttrN,ObjectEncode};
126		    _ ->
127			false
128		end;
129	    _ ->
130		case D#type.tablecinf of
131		    [{objfun,_}|_] ->
132			%% when the simpletableattributes was at an
133			%% outer level and the objfun has been passed
134			%% through the function call
135			{"got objfun through args","ObjFun"};
136		    _ ->
137			false
138		end
139	end,
140
141    gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
142
143    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
144	++
145	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
146	      number = asn1ct_gen_ber:decode_type(SeqOrSet),
147	      form = ?CONSTRUCTED,
148	      type = 'IMPLICIT'}],
149    emit([nl,"   BytesSoFar = "]),
150    case SeqOrSet of
151	'SET' when (D#type.def)#'SET'.sorted == dynamic ->
152	    emit("?RT_BER:dynamicsort_SET_components(["),
153	    mkvlist(asn1ct_name:all(encBytes)),
154	    emit(["]),",nl]);
155	_ ->
156	    emit("["),
157	    mkvlist(asn1ct_name:all(encBytes)),
158	    emit(["],",nl])
159    end,
160    emit("  LenSoFar = "),
161    case asn1ct_name:all(encLen) of
162	[] -> emit("0");
163	AllLengths ->
164	    mkvplus(AllLengths)
165    end,
166    emit([",",nl]),
167% emit(["{TagBytes,Len} = ?RT_BER:encode_tags(TagIn ++ ",
168 emit(["  ?RT_BER:encode_tags(TagIn ++ ",
169		  {asis,MyTag},", BytesSoFar, LenSoFar).",nl]).
170
171
172gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
173    asn1ct_name:start(),
174%    asn1ct_name:new(term),
175    asn1ct_name:new(tag),
176    #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
177    Ext = extensible(CList),
178    CompList = case CList of
179		   {Rl,El}  -> Rl ++ El;
180		   _ -> CList
181	       end,
182
183    emit({"   %%-------------------------------------------------",nl}),
184    emit({"   %% decode tag and length ",nl}),
185    emit({"   %%-------------------------------------------------",nl}),
186
187    asn1ct_name:new(rb),
188    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
189	++
190	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
191	      number = asn1ct_gen_ber:decode_type('SEQUENCE'),
192	      form = ?CONSTRUCTED,
193	      type = 'IMPLICIT'}],
194    emit(["   {{_,",asn1ct_gen_ber:unused_var("Len",D#type.def),"},",{next,bytes},",",{curr,rb},
195	  "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
196	  {curr,bytes},", OptOrMand), ",nl]),
197    asn1ct_name:new(bytes),
198    asn1ct_name:new(len),
199
200    case CompList of
201	[] -> true;
202	_ ->
203	    emit({"{",{next,bytes},
204		  ",RemBytes} = ?RT_BER:split_list(",
205		  {curr,bytes},
206		  ",", {prev,len},"),",nl}),
207	    asn1ct_name:new(bytes)
208    end,
209
210    {DecObjInf,UniqueFName,ValueIndex} =
211	case TableConsInfo of
212	    #simpletableattributes{objectsetname=ObjectSet,
213				   c_name=AttrN,
214				   usedclassfield=UniqueFieldName,
215				   uniqueclassfield=UniqueFieldName,
216				   valueindex=ValIndex
217				  } ->
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		    %%AttributeName = asn1ct_gen:un_hyphen_var(AttrN),
226		    true -> % when component relation constraint establish
227			%% relation from a component to another components
228			%% subtype component
229			{{AttrN,{deep,ObjectSet,UniqueFieldName,
230					 ValIndex}},
231			 UniqueFieldName,ValIndex};
232		    false ->
233			{{AttrN,ObjectSet},UniqueFieldName,ValIndex}
234		end;
235	    _ ->
236		{false,false,false}
237	end,
238    case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
239	no_terms -> % an empty sequence
240	    emit([nl,nl]),
241	    demit({"Result = "}), %dbg
242	    %% return value as record
243	    asn1ct_name:new(rb),
244	    emit(["   {{'",asn1ct_gen:list2rname(Typename),"'}, ",{curr,bytes},",",nl,"    "]),
245	    asn1ct_gen_ber:add_removed_bytes(),
246	    emit(["}.",nl]);
247	{LeadingAttrTerm,PostponedDecArgs} ->
248	    emit([com,nl,nl]),
249	    case {LeadingAttrTerm,PostponedDecArgs} of
250		{[],[]} ->
251		    ok;
252		{_,[]} ->
253		    ok;
254		{[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
255		    DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
256		    ValueMatch = value_match(ValueIndex,Term),
257		    emit([DecObj," =",nl,"   'getdec_",ObjSet,"'(",
258%			  {asis,UniqueFName},", ",Term,"),",nl}),
259			  {asis,UniqueFName},", ",ValueMatch,"),",nl]),
260		    gen_dec_postponed_decs(DecObj,PostponedDecArgs)
261	    end,
262	    demit({"Result = "}), %dbg
263	    %% return value as record
264	    asn1ct_name:new(rb),
265	    asn1ct_name:new(bytes),
266	    ExtStatus = case Ext of
267			    {ext,_,_} -> ext;
268			    noext -> noext
269			end,
270	    emit(["   {",{next,bytes},",",{curr,rb},"} = ?RT_BER:restbytes2(RemBytes, ",
271		  {curr,bytes},",",ExtStatus,"),",nl]),
272	    asn1ct_name:new(rb),
273	    case Typename of
274		['EXTERNAL'] ->
275		    emit(["   OldFormat={'",asn1ct_gen:list2rname(Typename),
276			  "', "]),
277		    mkvlist(asn1ct_name:all(term)),
278		    emit(["},",nl]),
279		    emit(["   ASN11994Format =",nl,
280			  "      asn1rt_check:transform_to_EXTERNAL1994",
281			  "(OldFormat),",nl]),
282		    emit(["   {ASN11994Format,",{next,bytes},", "]);
283		_ ->
284		    emit(["   {{'",asn1ct_gen:list2rname(Typename),"', "]),
285		    mkvlist(asn1ct_name:all(term)),
286		    emit(["}, ",{next,bytes},", "])
287	    end,
288	    asn1ct_gen_ber:add_removed_bytes(),
289	    emit(["}.",nl])
290    end.
291
292gen_dec_postponed_decs(_,[]) ->
293    emit(nl);
294gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,_Tag,OptOrMand}|Rest]) ->
295%    asn1ct_name:new(term),
296    asn1ct_name:new(tmpterm),
297    asn1ct_name:new(reason),
298
299    emit({"{",Term,", _, _} = ",nl}),
300    N = case OptOrMand of
301	    mandatory -> 0;
302	    'OPTIONAL' ->
303		emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
304		6;
305	    {'DEFAULT',Val} ->
306		emit_opt_or_mand_check(Val,TmpTerm),
307		6
308	end,
309    emit({indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
310%	  ", ",TmpTerm,", ", {asis,Tag},", ",{asis,PFNList},")) of",nl}),
311	  ", ",TmpTerm,", [], ",{asis,PFNList},")) of",nl}),
312    emit({indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl}),
313    emit({indent(N+9),"exit({'Type not compatible with table constraint',",
314	  {curr,reason},"});",nl}),
315    emit({indent(N+6),{curr,tmpterm}," ->",nl}),
316    emit({indent(N+9),{curr,tmpterm},nl}),
317
318    case OptOrMand of
319	mandatory -> emit([indent(N+3),"end,",nl]);
320	_ ->
321	    emit([indent(N+3),"end",nl,
322		  indent(3),"end,",nl])
323    end,
324%    emit({indent(3),"end,",nl}),
325    gen_dec_postponed_decs(DecObj,Rest).
326
327
328emit_opt_or_mand_check(Value,TmpTerm) ->
329    emit([indent(3),"case ",TmpTerm," of",nl,
330	  indent(6),{asis,Value}," -> {",{asis,Value},",[],[]};",nl,
331	  indent(6),"_ ->",nl]).
332
333%%============================================================================
334%%  Encode/decode SET
335%%
336%%============================================================================
337
338gen_encode_set(Erules,Typename,D) when record(D,type) ->
339    gen_encode_sequence(Erules,Typename,D).
340
341gen_decode_set(Erules,Typename,D) when record(D,type) ->
342    asn1ct_name:start(),
343    asn1ct_name:new(term),
344    asn1ct_name:new(tag),
345    #'SET'{components=TCompList} = D#type.def,
346    Ext = extensible(TCompList),
347    CompList = case TCompList of
348		   {Rl,El} -> Rl ++ El;
349		   _ -> TCompList
350	       end,
351
352    emit(["   %%-------------------------------------------------",nl]),
353    emit(["   %% decode tag and length ",nl]),
354    emit(["   %%-------------------------------------------------",nl]),
355
356    asn1ct_name:new(rb),
357    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
358	++
359	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
360	      number = asn1ct_gen_ber:decode_type('SET'),
361	      form = ?CONSTRUCTED,
362	      type = 'IMPLICIT'}],
363    emit(["   {{_,Len},",{next,bytes},",",{curr,rb},
364	  "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
365	  {curr,bytes},", OptOrMand), ",nl]),
366    asn1ct_name:new(bytes),
367    asn1ct_name:new(len),
368    asn1ct_name:new(rb),
369
370    emit(["   {SetTerm, SetBytes, ",{curr,rb},"} = ?RT_BER:decode_set(0, Len, ",
371	  {curr,bytes},", OptOrMand, ",
372	  "fun 'dec_",asn1ct_gen:list2name(Typename),"_fun'/2, []),",nl]),
373
374    asn1ct_name:new(rb),
375    emit(["   'dec_",asn1ct_gen:list2name(Typename),"_result'(lists:sort(SetTerm), SetBytes, "]),
376    asn1ct_gen_ber:add_removed_bytes(),
377    emit([").",nl,nl,nl]),
378
379    emit({"%%-------------------------------------------------",nl}),
380    emit({"%% Set loop fun for ",asn1ct_gen:list2name(Typename),nl}),
381    emit({"%%-------------------------------------------------",nl}),
382
383    asn1ct_name:clear(),
384    asn1ct_name:new(term),
385    emit(["'dec_",asn1ct_gen:list2name(Typename),"_fun'(",{curr,bytes},
386	  ", OptOrMand) ->",nl]),
387
388    asn1ct_name:new(bytes),
389    gen_dec_set(Erules,Typename,CompList,1,Ext),
390
391    emit(["      %% tag not found, if extensionmark we should skip bytes here",nl]),
392    emit([indent(6),"_ -> {[], Bytes,0}",nl]),
393    emit([indent(3),"end.",nl,nl,nl]),
394
395
396    emit({"%%-------------------------------------------------",nl}),
397    emit({"%% Result ",asn1ct_gen:list2name(Typename),nl}),
398    emit({"%%-------------------------------------------------",nl}),
399
400    asn1ct_name:clear(),
401    emit({"'dec_",asn1ct_gen:list2name(Typename),"_result'(",
402	  asn1ct_gen_ber:unused_var("TermList",D#type.def),", Bytes, Rb) ->",nl}),
403
404    case gen_dec_set_result(Erules,Typename,CompList) of
405	no_terms ->
406	    %% return value as record
407	    asn1ct_name:new(rb),
408	    emit({"   {{'",asn1ct_gen:list2rname(Typename),"'}, Bytes, Rb}.",nl});
409	_ ->
410	    emit({nl,"   case ",{curr,termList}," of",nl}),
411	    emit({"      [] -> {{'",asn1ct_gen:list2rname(Typename),"', "}),
412	    mkvlist(asn1ct_name:all(term)),
413	    emit({"}, Bytes, Rb};",nl}),
414	    emit({"      ExtraAtt -> exit({error,{asn1,{too_many_attributes, ExtraAtt}}})",nl}),
415	    emit({"   end.",nl}),
416	    emit({nl,nl,nl})
417    end.
418
419
420%%===============================================================================
421%%===============================================================================
422%%===============================================================================
423%%  Encode/decode SEQUENCE OF and SET OF
424%%===============================================================================
425%%===============================================================================
426%%===============================================================================
427
428gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
429    asn1ct_name:start(),
430    {SeqOrSetOf, Cont} = D#type.def,
431
432    Objfun = case D#type.tablecinf of
433		 [{objfun,_}|_R] ->
434		     ", ObjFun";
435		 _ ->
436		     ""
437	     end,
438
439    emit({"   {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
440	  "_components'(Val",Objfun,",[],0),",nl}),
441
442    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
443	++
444	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
445	      number = asn1ct_gen_ber:decode_type(SeqOrSetOf),
446	      form = ?CONSTRUCTED,
447	      type = 'IMPLICIT'}],
448%    gen_encode_tags(Erules,MyTag,"EncLen","EncBytes"),
449	    emit(["   ?RT_BER:encode_tags(TagIn ++ ",
450		  {asis,MyTag},", EncBytes, EncLen).",nl,nl]),
451
452    gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
453%     gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",0,
454% 		 mandatory,"{EncBytes,EncLen} = "),
455
456
457gen_decode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
458    asn1ct_name:start(),
459    {SeqOrSetOf, TypeTag, Cont} =
460	case D#type.def of
461	    {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
462	    {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
463	end,
464    TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
465
466    emit({"   %%-------------------------------------------------",nl}),
467    emit({"   %% decode tag and length ",nl}),
468    emit({"   %%-------------------------------------------------",nl}),
469
470    asn1ct_name:new(rb),
471    MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
472	++
473	[#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
474	      number = asn1ct_gen_ber:decode_type(TypeTag),
475	      form = ?CONSTRUCTED,
476	      type = 'IMPLICIT'}],
477    emit(["   {{_,Len},",{next,bytes},",",{curr,rb},
478	  "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
479	  {curr,bytes},", OptOrMand), ",nl]),
480
481    emit(["   ?RT_BER:decode_components(",{curr,rb}]),
482    InnerType = asn1ct_gen:get_inner(Cont#type.def),
483    ContName = case asn1ct_gen:type(InnerType) of
484		   Atom when atom(Atom) -> Atom;
485		   _ -> TypeNameSuffix
486	       end,
487    emit([", Len, ",{next,bytes},", "]),
488%    NewCont =
489%	case Cont#type.def of
490%	    {'ENUMERATED',_,Components}->
491%		Cont#type{def={'ENUMERATED',Components}};
492%	    _ -> Cont
493%	end,
494     ObjFun =
495	case D#type.tablecinf of
496	    [{objfun,_}|_R] ->
497		", ObjFun";
498	    _ ->
499		[]
500	end,
501    gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
502    emit([", []).",nl,nl,nl]).
503
504
505gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
506  when record(Cont,type)->
507
508    {Objfun,ObjFun_novar,EncObj} =
509	case Cont#type.tablecinf of
510	    [{objfun,_}|_R] ->
511		{", ObjFun",", _",{no_attr,"ObjFun"}};
512	    _ ->
513		{"","",false}
514	end,
515    emit(["'enc_",asn1ct_gen:list2name(Typename),
516	  "_components'([]",ObjFun_novar,", AccBytes, AccLen) -> ",nl]),
517
518    case catch lists:member(der,get(encoding_options)) of
519	true ->
520	    emit([indent(3),
521		  "{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
522	_ ->
523	    emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
524    end,
525    emit(["'enc_",asn1ct_gen:list2name(Typename),
526	  "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
527    TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
528    gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
529		 mandatory,"{EncBytes,EncLen} = ",EncObj),
530    emit([",",nl]),
531    emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
532	  "_components'(T",Objfun,","]),
533    emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
534
535%%============================================================================
536%%  Encode/decode CHOICE
537%%
538%%============================================================================
539
540gen_encode_choice(Erules,Typename,D) when record(D,type) ->
541    ChoiceTag = D#type.tag,
542    {'CHOICE',CompList} = D#type.def,
543    Ext = extensible(CompList),
544    CompList1 = case CompList of
545		    {Rl,El} -> Rl ++ El;
546		    _ -> CompList
547		end,
548    gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
549    emit({nl,nl}).
550
551gen_decode_choice(Erules,Typename,D) when record(D,type) ->
552    asn1ct_name:start(),
553    asn1ct_name:new(bytes),
554    ChoiceTag = D#type.tag,
555    {'CHOICE',CompList} = D#type.def,
556    Ext = extensible(CompList),
557    CompList1 = case CompList of
558		    {Rl,El} -> Rl ++ El;
559		    _ -> CompList
560		end,
561    gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
562    emit({".",nl}).
563
564
565%%============================================================================
566%%  Encode SEQUENCE
567%%
568%%============================================================================
569
570gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],Pos,Ext,EncObj) ->
571    asn1ct_name:new(encBytes),
572    asn1ct_name:new(encLen),
573    Element =
574	case TopType of
575	    ['EXTERNAL'] ->
576		io_lib:format("?RT_BER:cindex(~w,NewVal,~w)",[Pos+1,Cname]);
577	    _ ->
578		io_lib:format("?RT_BER:cindex(~w,Val,~w)",[Pos+1,Cname])
579	end,
580    InnerType = asn1ct_gen:get_inner(Type#type.def),
581    print_attribute_comment(InnerType,Pos,Prop),
582    gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
583    case Rest of
584	[] ->
585	    emit({com,nl});
586	_ ->
587	    emit({com,nl}),
588	    gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj)
589    end;
590
591gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
592	true.
593
594%%============================================================================
595%%  Decode SEQUENCE
596%%
597%%============================================================================
598
599gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
600    gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
601
602
603gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
604    {LA,PostponedDec} =
605	gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
606			  Ext,DecObjInf),
607    case Rest of
608	[] ->
609	    {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
610	_ ->
611	    emit({com,nl}),
612%	    asn1ct_name:new(term),
613	    asn1ct_name:new(bytes),
614	    gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
615				   LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
616    end;
617
618gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
619    no_terms.
620%%gen_dec_sequence_call1(Erules,_TopType,[],Num,_) ->
621%%    true.
622
623
624
625%%----------------------------
626%%SEQUENCE mandatory
627%%----------------------------
628
629gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
630    InnerType =
631	case Type#type.def of
632	    #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
633	    _ -> asn1ct_gen:get_inner(Type#type.def)
634	end,
635% 	case asn1ct_gen:get_constraint(Type#type.constraint,
636% 				       tableconstraint_info) of
637% 	    no ->
638% 		asn1ct_gen:get_inner(Type#type.def);
639% 	    _ ->
640% 		Type#type.def
641% 	end,
642    Prop1 = case {Prop,Ext} of
643		{mandatory,{ext,Epos,_}} when Pos >= Epos ->
644		    'OPTIONAL';
645		_ ->
646		    Prop
647	    end,
648    print_attribute_comment(InnerType,Pos,Prop1),
649    emit("   "),
650
651    case {InnerType,DecObjInf} of
652	{{typefield,_},NotFalse} when NotFalse /= false ->
653	    asn1ct_name:new(term),
654	    asn1ct_name:new(tmpterm),
655	    emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
656	{{objectfield,_,_},_} ->
657	    asn1ct_name:new(term),
658	    asn1ct_name:new(tmpterm),
659	    emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
660	_ ->
661	    asn1ct_name:new(term),
662	    emit({"{",{curr,term},",",{next,bytes},",",{next,rb},"} = "})
663    end,
664    asn1ct_name:new(rb),
665    PostponedDec =
666	gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
667    asn1ct_name:new(form),
668    PostponedDec.
669
670
671%%-------------------------------------
672%%  Decode SET
673%%-------------------------------------
674
675gen_dec_set(Erules,TopType,CompList,Pos,_Ext) ->
676    TagList = get_all_choice_tags(CompList),
677    emit({indent(3),
678	  {curr,tagList}," = ",{asis,TagList},",",nl}),
679    emit({indent(3),
680	  "case ?RT_BER:check_if_valid_tag(Bytes, ",
681	  {curr,tagList},", OptOrMand) of",nl}),
682    asn1ct_name:new(tagList),
683    asn1ct_name:new(rbCho),
684    asn1ct_name:new(choTags),
685    gen_dec_set_cases(Erules,TopType,CompList,TagList,Pos),
686    asn1ct_name:new(tag),
687    asn1ct_name:new(bytes).
688
689
690
691gen_dec_set_cases(_,_,[],_,_) ->
692    ok;
693gen_dec_set_cases(Erules,TopType,[H|T],List,Pos) ->
694    case H of
695	{'EXTENSIONMARK', _, _} ->
696	    gen_dec_set_cases(Erules,TopType,T,List,Pos);
697	_ ->
698	    Name = H#'ComponentType'.name,
699	    Type = H#'ComponentType'.typespec,
700
701	    emit({indent(6),"'",Name,"' ->",nl}),
702	    case Type#type.def of
703		{'CHOICE',_NewCompList} ->
704		    gen_dec_set_cases_choice(Erules,TopType,H,Pos);
705		_ ->
706		    gen_dec_set_cases_type(Erules,TopType,H,Pos)
707	    end,
708	    gen_dec_set_cases(Erules,TopType,T,List,Pos+1)
709    end.
710
711
712
713
714gen_dec_set_cases_choice(_Erules,TopType,H,Pos) ->
715    Cname = H#'ComponentType'.name,
716    Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
717	   || X <- (H#'ComponentType'.typespec)#type.tag],
718    asn1ct_name:new(rbCho),
719    emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
720    emit({"'dec_",asn1ct_gen:list2name([Cname|TopType]),
721	  "'(Bytes,OptOrMand,",{asis,Tag},"),",nl}),
722    emit(["      {{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
723    emit([";",nl,nl]).
724
725
726gen_dec_set_cases_type(Erules,TopType,H,Pos) ->
727    Cname = H#'ComponentType'.name,
728    Type = H#'ComponentType'.typespec,
729    %% always use Prop = mandatory here    Prop = H#'ComponentType'.prop,
730
731    asn1ct_name:new(rbCho),
732    emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
733    asn1ct_name:delete(bytes),
734    %% we have already seen the tag so now we must find the value
735    %% that why we always use 'mandatory' here
736    gen_dec_line(Erules,TopType,Cname,[],Type,mandatory,decObjInf),
737    asn1ct_name:new(bytes),
738
739    emit([",",nl]),
740    emit(["{{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
741    emit([";",nl,nl]).
742
743
744%%---------------------------------
745%%  Decode SET result
746%%---------------------------------
747
748gen_dec_set_result(Erules,TopType,{CompList,_ExtList}) ->
749    gen_dec_set_result1(Erules,TopType, CompList, 1);
750gen_dec_set_result(Erules,TopType,CompList) ->
751    gen_dec_set_result1(Erules,TopType, CompList, 1).
752
753gen_dec_set_result1(Erules,TopType,
754		   [#'ComponentType'{name=Cname,
755				     typespec=Type,
756				     prop=Prop}|Rest],Num) ->
757    gen_dec_set_component(Erules,TopType,Cname,Type,Num,Prop),
758    case Rest of
759	[] ->
760	    true;
761	_ ->
762	    gen_dec_set_result1(Erules,TopType,Rest,Num+1)
763    end;
764
765gen_dec_set_result1(_Erules,_TopType,[],1) ->
766    no_terms;
767gen_dec_set_result1(_Erules,_TopType,[],_Num) ->
768    true.
769
770
771gen_dec_set_component(_Erules,_TopType,_Cname,Type,Pos,Prop) ->
772    InnerType = asn1ct_gen:get_inner(Type#type.def),
773    print_attribute_comment(InnerType,Pos,Prop),
774    emit({"   {",{next,term},com,{next,termList},"} =",nl}),
775    emit({"      case ",{curr,termList}," of",nl}),
776    emit({"          [{",Pos,com,{curr,termTmp},"}|",
777	  {curr,rest},"] -> "}),
778    emit({"{",{curr,termTmp},com,
779	  {curr,rest},"};",nl}),
780    case Prop of
781	'OPTIONAL' ->
782	    emit([indent(10),"_ -> {asn1_NOVALUE, ",{curr,termList},"}",nl]);
783	{'DEFAULT', DefVal} ->
784	    emit([indent(10),
785		  "_ -> {",{asis,DefVal},", ",{curr,termList},"}",nl]);
786	mandatory ->
787	    emit([indent(10),
788		  "_ -> exit({error,{asn1,{mandatory_attribute_no, ",
789		  Pos,", missing}}})",nl])
790    end,
791    emit([indent(6),"end,",nl]),
792    asn1ct_name:new(rest),
793    asn1ct_name:new(term),
794    asn1ct_name:new(termList),
795    asn1ct_name:new(termTmp).
796
797
798%%---------------------------------------------
799%%  Encode CHOICE
800%%---------------------------------------------
801%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
802
803
804gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
805    gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
806
807gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext) ->
808    asn1ct_name:clear(),
809    emit({"   {EncBytes,EncLen} = case element(1,Val) of",nl}),
810    gen_enc_choice2(Erules,TopType,CompList),
811    emit([nl,"   end,",nl,nl]),
812    NewTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- Tag],
813%    gen_encode_tags(Erules,NewTag,"EncLen","EncBytes").
814   emit(["?RT_BER:encode_tags(TagIn ++",{asis,NewTag},", EncBytes, EncLen).",nl]).
815
816
817
818gen_enc_choice2(Erules,TopType,[H1|T]) when record(H1,'ComponentType') ->
819    Cname = H1#'ComponentType'.name,
820    Type = H1#'ComponentType'.typespec,
821    emit({"      ",{asis,Cname}," ->",nl}),
822    {Encobj,Assign} =
823% 	case asn1ct_gen:get_constraint(Type#type.constraint,
824% 				       tableconstraint_info) of
825	case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
826						      componentrelation)} of
827	    {#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
828		asn1ct_name:new(tmpBytes),
829		asn1ct_name:new(encBytes),
830		asn1ct_name:new(encLen),
831		Emit = ["{",{curr,tmpBytes},", _} = "],
832		{{no_attr,"ObjFun"},Emit};
833	    _ ->
834		{false,[]}
835	end,
836    gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
837		 mandatory,Assign,Encobj),
838    case Encobj of
839	false -> ok;
840	_ ->
841	    emit({",",nl,indent(9),"{",{curr,encBytes},", ",
842		  {curr,encLen},"}"})
843    end,
844    emit({";",nl}),
845    case T of
846	[] ->
847	    emit([indent(6), "Else -> ",nl,
848		  indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
849	_ ->
850	    true
851    end,
852    gen_enc_choice2(Erules,TopType,T);
853
854gen_enc_choice2(_,_,[])  ->
855    true.
856
857
858
859
860%%--------------------------------------------
861%%  Decode CHOICE
862%%--------------------------------------------
863
864gen_dec_choice(Erules,TopType, ChTag, CompList, Ext) ->
865    asn1ct_name:delete(bytes),
866    Tags = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- ChTag],
867
868    emit(["   {{_,Len},",{next,bytes},
869	  ", RbExp} = ?RT_BER:check_tags(TagIn++",
870	  {asis,Tags},", ",
871	  {curr,bytes},", OptOrMand),",nl]),
872    asn1ct_name:new(bytes),
873    asn1ct_name:new(len),
874    gen_dec_choice_indef_funs(Erules),
875    case Erules of
876	ber_bin ->
877	    emit([indent(3),"case ",{curr,bytes}," of",nl]);
878	ber ->
879	    emit([indent(3),
880		  "case (catch ?RT_BER:peek_tag(",{curr,bytes},")) of",nl])
881    end,
882    asn1ct_name:new(tagList),
883    asn1ct_name:new(choTags),
884    gen_dec_choice_cases(Erules,TopType,CompList),
885    case Ext of
886	noext ->
887	    emit([indent(6), {curr,else}," -> ",nl]),
888	    emit([indent(9),"case OptOrMand of",nl,
889		  indent(12),"mandatory ->","exit({error,{asn1,",
890		  "{invalid_choice_tag,",{curr,else},"}}});",nl,
891		  indent(12),"_ ->","exit({error,{asn1,{no_optional_tag,",
892		  {curr,else},"}}})",nl,
893		  indent(9),"end",nl]);
894	_ ->
895	    emit([indent(6),"_ -> ",nl]),
896	    emit([indent(9),"{{asn1_ExtAlt,",{curr,bytes},"},",
897		  empty_lb(Erules),", RbExp}",nl])
898    end,
899    emit([indent(3),"end"]),
900    asn1ct_name:new(tag),
901    asn1ct_name:new(else).
902
903gen_dec_choice_indef_funs(Erules) ->
904    emit({indent(3),"IndefEndBytes = fun(indefinite,",indefend_match(Erules,used_var),
905	  ")-> R; (_,B)-> B end,",nl}),
906    emit({indent(3),"IndefEndRb = fun(indefinite,",indefend_match(Erules,unused_var),
907	  ")-> 2; (_,_)-> 0 end,",nl}).
908
909
910gen_dec_choice_cases(_,_, []) ->
911    ok;
912gen_dec_choice_cases(Erules,TopType, [H|T]) ->
913    asn1ct_name:push(rbCho),
914    Name = H#'ComponentType'.name,
915    emit([nl,"%% '",Name,"'",nl]),
916    Fcases  = fun([T1,T2|Tail],Fun) ->
917		      emit([indent(6),match_tag(Erules,T1)," ->",nl]),
918		      gen_dec_choice_cases_type(Erules,TopType, H),
919		      Fun([T2|Tail],Fun);
920		 ([T1],_) ->
921		      emit([indent(6),match_tag(Erules,T1)," ->",nl]),
922		      gen_dec_choice_cases_type(Erules,TopType, H)
923	      end,
924    Fcases(H#'ComponentType'.tags,Fcases),
925    asn1ct_name:pop(rbCho),
926    gen_dec_choice_cases(Erules,TopType, T).
927
928
929
930gen_dec_choice_cases_type(Erules,TopType,H) ->
931    Cname = H#'ComponentType'.name,
932    Type = H#'ComponentType'.typespec,
933    Prop = H#'ComponentType'.prop,
934    emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
935    gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
936    emit([",",nl,indent(9),"{{",{asis,Cname},
937	  ", Dec}, IndefEndBytes(Len,Rest), RbExp + ",
938	  {curr,rbCho}," + IndefEndRb(Len,Rest)};",nl,nl]).
939
940encode_tag_val(Erules,{Class,TagNo}) when integer(TagNo) ->
941    Rtmod = rtmod(Erules),
942    Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
943				  0,TagNo});
944encode_tag_val(Erules,{Class,TypeName}) ->
945    Rtmod = rtmod(Erules),
946    Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
947				  0,asn1ct_gen_ber:decode_type(TypeName)}).
948
949
950match_tag(ber_bin,Arg) ->
951    match_tag_with_bitsyntax(Arg);
952match_tag(Erules,Arg) ->
953    io_lib:format("~p",[encode_tag_val(Erules,Arg)]).
954
955match_tag_with_bitsyntax({Class,TagNo}) when integer(TagNo) ->
956    match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
957				  0,TagNo});
958match_tag_with_bitsyntax({Class,TypeName}) ->
959    match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
960				  0,asn1ct_gen_ber:decode_type(TypeName)}).
961
962match_tag_with_bitsyntax1({Class, _Form, TagNo}) when (TagNo =< 30) ->
963    io_lib:format("<<~p:2,_:1,~p:5,_/binary>>",[Class bsr 6,TagNo]);
964
965match_tag_with_bitsyntax1({Class, _Form, TagNo}) ->
966    {Octets,Len} = mk_object_val(TagNo),
967    OctForm = case Len of
968		 1 -> "~p";
969		 2 -> "~p,~p";
970		 3 -> "~p,~p,~p";
971		 4 -> "~p,~p,~p,~p"
972	     end,
973    io_lib:format("<<~p:2,_:1,31:5," ++ OctForm ++ ",_/binary>>",
974		  [Class bsr 6] ++ Octets).
975
976%%%%%%%%%%%
977%% mk_object_val(Value) -> {OctetList, Len}
978%% returns a Val as a list of octets, the 8 bit is allways set to one except
979%% for the last octet, where its 0
980%%
981
982
983mk_object_val(Val) when Val =< 127 ->
984    {[255 band Val], 1};
985mk_object_val(Val) ->
986    mk_object_val(Val bsr 7, [Val band 127], 1).
987mk_object_val(0, Ack, Len) ->
988    {Ack, Len};
989mk_object_val(Val, Ack, Len) ->
990    mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
991
992
993get_all_choice_tags(ComponentTypeList) ->
994    get_all_choice_tags(ComponentTypeList,[]).
995
996get_all_choice_tags([],TagList) ->
997    TagList;
998get_all_choice_tags([H|T],TagList)  ->
999    Tags = H#'ComponentType'.tags,
1000    get_all_choice_tags(T, TagList ++ [{H#'ComponentType'.name, Tags}]).
1001
1002
1003
1004%%---------------------------------------
1005%% Generate the encode/decode code
1006%%---------------------------------------
1007
1008gen_enc_line(Erules,TopType,Cname,
1009	     Type=#type{constraint=[{componentrelation,_,_}],
1010			def=#'ObjectClassFieldType'{type={typefield,_}}},
1011	     Element,Indent,OptOrMand=mandatory,EncObj)
1012  when list(Element) ->
1013    asn1ct_name:new(tmpBytes),
1014    gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
1015		 ["{",{curr,tmpBytes},",_} = "],EncObj);
1016gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
1017  when list(Element) ->
1018    gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
1019		 ["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
1020
1021gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
1022  when list(Element) ->
1023    IndDeep = indent(Indent),
1024
1025    Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
1026	   || X <- Type#type.tag],
1027    InnerType = asn1ct_gen:get_inner(Type#type.def),
1028    WhatKind = asn1ct_gen:type(InnerType),
1029    emit(IndDeep),
1030    emit(Assign),
1031    gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
1032		       Element),
1033    case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
1034					 componentrelation)} of
1035% 	#type{constraint=[{tableconstraint_info,RefedFieldName}],
1036% 	      def={typefield,_}} ->
1037	{#type{def=#'ObjectClassFieldType'{type={typefield,_},
1038					   fieldname=RefedFieldName}},
1039	 {componentrelation,_,_}} ->
1040	    {_LeadingAttrName,Fun} = EncObj,
1041	    case RefedFieldName of
1042		{notype,T} ->
1043		    throw({error,{notype,type_from_object,T}});
1044		{Name,RestFieldNames} when atom(Name) ->
1045		    case OptOrMand of
1046			mandatory -> ok;
1047			_ ->
1048%			    emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
1049			    emit(["{",{curr,tmpBytes},", _} = "])
1050%%			    asn1ct_name:new(tmpBytes),
1051%%			    asn1ct_name:new(tmpLen)
1052		    end,
1053		    emit({Fun,"(",{asis,Name},", ",Element,", [], ",
1054			  {asis,RestFieldNames},"),",nl}),
1055		    emit(IndDeep),
1056		    case OptOrMand of
1057			mandatory ->
1058			    emit({"{",{curr,encBytes},", ",{curr,encLen},"} = "}),
1059			    emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
1060				  ",",{asis,Tag},")"});
1061			_ ->
1062%			    emit({"{",{next,tmpBytes},", _} = "}),
1063			    emit({"{",{next,tmpBytes},", ",{curr,tmpLen},
1064				  "} = "}),
1065			    emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
1066				  ",",{asis,Tag},"),",nl}),
1067			    emit(IndDeep),
1068			    emit({"{",{next,tmpBytes},", ",{curr,tmpLen},"}"})
1069		    end;
1070		_ ->
1071		    throw({asn1,{'internal error'}})
1072	    end;
1073% 	#type{constraint=[{tableconstraint_info,_}],
1074% 	      def={objectfield,PrimFieldName1,PFNList}} ->
1075	{{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
1076					PFNList}},_},
1077	 {componentrelation,_,_}} ->
1078	    %% this is when the dotted list in the FieldName has more
1079	    %% than one element
1080	    {_LeadingAttrName,Fun} = EncObj,
1081	    emit({"?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
1082		  ", ",Element,", ",{asis,PFNList},"),",{asis,Tag},")"});
1083	_ ->
1084	    case WhatKind of
1085		{primitive,bif} ->
1086		    EncType =
1087			case Type#type.def of
1088			    #'ObjectClassFieldType'{
1089					     type={fixedtypevaluefield,
1090						   _,Btype}} ->
1091				Btype;
1092			    _ ->
1093				Type
1094			end,
1095		    asn1ct_gen_ber:gen_encode_prim(ber,EncType,{asis,Tag},
1096						   Element);
1097		{notype,_} ->
1098		    emit({"'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"});
1099		'ASN1_OPEN_TYPE' ->
1100		    asn1ct_gen_ber:gen_encode_prim(ber,Type#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
1101		_ ->
1102		    {EncFunName, _, _} =
1103			mkfuncname(TopType,Cname,WhatKind,enc),
1104		    case {WhatKind,Type#type.tablecinf,EncObj} of
1105			{{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
1106			    emit([EncFunName,"(",Element,", ",{asis,Tag},
1107				  ", ",Fun,")"]);
1108			_ ->
1109			    emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
1110		    end
1111	    end
1112    end,
1113    case OptOrMand of
1114	mandatory -> true;
1115	_ ->
1116	    emit({nl,indent(7),"end"})
1117    end.
1118
1119
1120
1121gen_optormand_case(mandatory,_,_,_,_,_,_, _) ->
1122    ok;
1123gen_optormand_case('OPTIONAL',Erules,_,_,_,_,_,Element) ->
1124    emit({" case ",Element," of",nl}),
1125    emit({indent(9),"asn1_NOVALUE -> {",
1126	  empty_lb(Erules),",0};",nl}),
1127    emit({indent(9),"_ ->",nl,indent(12)});
1128gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
1129		   InnerType,WhatKind,Element) ->
1130    CurrMod = get(currmod),
1131    case catch lists:member(der,get(encoding_options)) of
1132	true ->
1133	    emit(" case catch "),
1134	    asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
1135				      WhatKind,{asis,DefaultValue},
1136				      Element),
1137	    emit({" of",nl}),
1138	    emit({indent(12),"true -> {[],0};",nl});
1139	_ ->
1140	    emit({" case ",Element," of",nl}),
1141	    emit({indent(9),"asn1_DEFAULT -> {",
1142		  empty_lb(Erules),
1143		  ",0};",nl}),
1144	    case DefaultValue of
1145		#'Externalvaluereference'{module=CurrMod,
1146					  value=V} ->
1147		    emit({indent(9),"?",{asis,V}," -> {",
1148			  empty_lb(Erules),",0};",nl});
1149		_ ->
1150		    emit({indent(9),{asis,
1151				     DefaultValue}," -> {",
1152			  empty_lb(Erules),",0};",nl})
1153	    end
1154    end,
1155    emit({indent(9),"_ ->",nl,indent(12)}).
1156
1157
1158
1159
1160gen_dec_line_sof(_Erules,TopType,Cname,Type,ObjFun) ->
1161
1162    Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
1163	   || X <- Type#type.tag],
1164    InnerType = asn1ct_gen:get_inner(Type#type.def),
1165    WhatKind = asn1ct_gen:type(InnerType),
1166    case WhatKind of
1167	{primitive,bif} ->
1168	    asn1ct_name:delete(len),
1169
1170	    asn1ct_name:new(len),
1171	    emit(["fun(FBytes,_,_)->",nl]),
1172	    EncType = case Type#type.def of
1173			    #'ObjectClassFieldType'{
1174					     type={fixedtypevaluefield,
1175						   _,Btype}} ->
1176				Btype;
1177			    _ ->
1178				Type
1179		      end,
1180	    asn1ct_gen_ber:gen_dec_prim(ber,EncType,"FBytes",Tag,
1181					[],no_length,?PRIMITIVE,
1182					mandatory),
1183	    emit([nl,"end, []"]);
1184	_ ->
1185	    case ObjFun of
1186		[] ->
1187		    {DecFunName, _, _} =
1188			mkfunname(TopType,Cname,WhatKind,dec,3),
1189		    emit([DecFunName,", ",{asis,Tag}]);
1190		_ ->
1191		    {DecFunName, _, _} =
1192			mkfunname(TopType,Cname,WhatKind,dec,4),
1193		    emit([DecFunName,", ",{asis,Tag},", ObjFun"])
1194	    end
1195    end.
1196
1197
1198gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf)  ->
1199    BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
1200    Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
1201	   || X <- Type#type.tag],
1202    InnerType =
1203	case Type#type.def of
1204	    #'ObjectClassFieldType'{type=OCFTType} ->
1205		OCFTType;
1206	    _ ->
1207		asn1ct_gen:get_inner(Type#type.def)
1208	end,
1209    PostpDec =
1210	case OptOrMand of
1211	    mandatory ->
1212		gen_dec_call(InnerType,Erules,TopType,Cname,Type,
1213			     BytesVar,Tag,mandatory,", mandatory, ",
1214			     DecObjInf,OptOrMand);
1215	    _ -> %optional or default
1216		case {CTags,Erules} of
1217		    {[CTag],ber_bin} ->
1218			emit(["case ",{curr,bytes}," of",nl]),
1219			emit([match_tag(Erules,CTag)," ->",nl]),
1220			PostponedDec =
1221			    gen_dec_call(InnerType,Erules,TopType,Cname,Type,
1222					 BytesVar,Tag,mandatory,
1223					 ", opt_or_default, ",DecObjInf,
1224					 OptOrMand),
1225			emit([";",nl]),
1226			emit(["_ ->",nl]),
1227			case OptOrMand of
1228			    {'DEFAULT', Def} ->
1229				emit(["{",{asis,Def},",",
1230				      BytesVar,", 0 }",nl]);
1231			    'OPTIONAL' ->
1232				emit(["{ asn1_NOVALUE, ",
1233				      BytesVar,", 0 }",nl])
1234			end,
1235			emit("end"),
1236			PostponedDec;
1237		    _ ->
1238			emit("case (catch "),
1239			PostponedDec =
1240			    gen_dec_call(InnerType,Erules,TopType,Cname,Type,
1241					 BytesVar,Tag,OptOrMand,
1242					 ", opt_or_default, ",DecObjInf,
1243					 OptOrMand),
1244			emit([") of",nl]),
1245			case OptOrMand of
1246			    {'DEFAULT', Def} ->
1247				emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
1248				      " -> {",{asis,Def},",",
1249				      BytesVar,", 0 };",nl]);
1250			    'OPTIONAL' ->
1251				emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
1252				      " -> { asn1_NOVALUE, ",
1253				      BytesVar,", 0 };",nl])
1254			end,
1255			asn1ct_name:new(casetmp),
1256			emit([{curr,casetmp},"-> ",{curr,casetmp},nl,"end"]),
1257			PostponedDec
1258		end
1259	end,
1260    case DecObjInf of
1261	{Cname,ObjSet} -> % this must be the component were an object is
1262	    %% chosen from the object set according to the table
1263	    %% constraint.
1264	    {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
1265	     PostpDec};
1266	_  -> {[],PostpDec}
1267    end.
1268
1269
1270gen_dec_call({typefield,_},Erules,_,_,Type,_,Tag,_,_,false,_) ->
1271    %%  this in case of a choice with typefield components
1272    asn1ct_name:new(reason),
1273    {FirstPFName,RestPFName} =
1274% 	asn1ct_gen:get_constraint(Type#type.constraint,
1275% 				  tableconstraint_info),
1276	(Type#type.def)#'ObjectClassFieldType'.fieldname,
1277    emit([nl,indent(6),"begin",nl]),
1278    emit([indent(9),"{OpenDec,TmpRest,TmpRbCho} =",nl,indent(12),
1279	  "?RT_BER:decode_open_type(",Erules,",",{curr,bytes},",",
1280	  {asis,Tag},"),",nl]),
1281    emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
1282	  ", OpenDec, [], ",{asis,RestPFName},
1283	  ")) of", nl]),%% ??? What about Tag
1284    emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
1285%%    emit({indent(15),"throw({runtime_error,{'Type not ",
1286%%	  "compatible with tableconstraint', OpenDec}});",nl}),
1287    emit([indent(15),"exit({'Type not ",
1288	  "compatible with table constraint', ",{curr,reason},"});",nl]),
1289    emit([indent(12),"{TmpDec,_ ,_} ->",nl]),
1290    emit([indent(15),"{TmpDec, TmpRest, TmpRbCho}",nl]),
1291    emit([indent(9),"end",nl,indent(6),"end",nl]),
1292    [];
1293gen_dec_call({typefield,_},_Erules,_,Cname,Type,_BytesVar,Tag,_,_,
1294	     _DecObjInf,OptOrMandComp) ->
1295    emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
1296    RefedFieldName =
1297	(Type#type.def)#'ObjectClassFieldType'.fieldname,
1298% 	asn1ct_gen:get_constraint(Type#type.constraint,
1299% 				  tableconstraint_info),
1300    [{Cname,RefedFieldName,
1301      asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1302%      asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
1303      asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
1304gen_dec_call({objectfield,PrimFieldName,PFNList},_Erules,_,Cname,_,_,Tag,_,_,_,
1305	     OptOrMandComp) ->
1306    emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
1307    [{Cname,{PrimFieldName,PFNList},
1308      asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1309%      asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
1310      asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
1311gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
1312	     OptOrMand,DecObjInf,_) ->
1313    WhatKind = asn1ct_gen:type(InnerType),
1314    gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
1315		  PrimOptOrMand,OptOrMand),
1316    case DecObjInf of
1317	{Cname,{_,OSet,UniqueFName,ValIndex}} ->
1318	    Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
1319	    ValueMatch = value_match(ValIndex,Term),
1320	    emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
1321%		  {asis,UniqueFName},", ",{curr,term},")"});
1322		  {asis,UniqueFName},", ",ValueMatch,")"});
1323	_ ->
1324	    ok
1325    end,
1326    [].
1327gen_dec_call1({primitive,bif},InnerType,Erules,_,_,Type,BytesVar,
1328	      Tag,OptOrMand,_) ->
1329    case InnerType of
1330	{fixedtypevaluefield,_,Btype} ->
1331	    asn1ct_gen_ber:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],no_length,
1332					?PRIMITIVE,OptOrMand);
1333	_ ->
1334	    asn1ct_gen_ber:gen_dec_prim(Erules,Type,BytesVar,Tag,[],no_length,
1335					?PRIMITIVE,OptOrMand)
1336    end;
1337gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,_,_,Type,BytesVar,
1338	      Tag,OptOrMand,_) ->
1339    asn1ct_gen_ber:gen_dec_prim(Erules,Type#type{def='ASN1_OPEN_TYPE'},
1340				BytesVar,Tag,[],no_length,
1341				?PRIMITIVE,OptOrMand);
1342gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,_,Tag,_,OptOrMand) ->
1343    {DecFunName,_,_} =
1344	mkfuncname(TopType,Cname,WhatKind,dec),
1345    case {WhatKind,Type#type.tablecinf} of
1346	{{constructed,bif},[{objfun,_}|_R]} ->
1347	    emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},", ObjFun)"});
1348	_ ->
1349	    emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},")"})
1350    end.
1351
1352
1353%%------------------------------------------------------
1354%% General and special help functions (not exported)
1355%%------------------------------------------------------
1356
1357
1358indent(N) ->
1359    lists:duplicate(N,32). % 32 = space
1360
1361
1362mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
1363    emit([{var,H},Sep]),
1364    mkvlist([T1|T], Sep);
1365mkvlist([H|T], Sep) ->
1366    emit([{var,H}]),
1367    mkvlist(T, Sep);
1368mkvlist([], _) ->
1369    true.
1370
1371mkvlist(L) ->
1372    mkvlist(L,", ").
1373
1374mkvplus(L) ->
1375    mkvlist(L," + ").
1376
1377extensible(CompList) when list(CompList) ->
1378    noext;
1379extensible({RootList,ExtList}) ->
1380    {ext,length(RootList)+1,length(ExtList)}.
1381
1382
1383print_attribute_comment(InnerType,Pos,Prop) ->
1384    CommentLine = "%%-------------------------------------------------",
1385    emit([nl,CommentLine]),
1386    case InnerType of
1387	{typereference,_,Name} ->
1388	    emit([nl,"%% attribute number ",Pos," with type ",Name]);
1389	{'Externaltypereference',_,XModule,Name} ->
1390	    emit([nl,"%% attribute number ",Pos,"   External ",XModule,":",Name]);
1391	_ ->
1392	    emit([nl,"%% attribute number ",Pos," with type ",InnerType])
1393    end,
1394    case Prop of
1395	mandatory ->
1396	    continue;
1397	{'DEFAULT', Def} ->
1398	    emit([" DEFAULT = ",{asis,Def}]);
1399	'OPTIONAL' ->
1400	    emit([" OPTIONAL"])
1401    end,
1402    emit([nl,CommentLine,nl]).
1403
1404
1405mkfuncname(TopType,Cname,WhatKind,DecOrEnc) ->
1406    CurrMod = get(currmod),
1407    case WhatKind of
1408	#'Externaltypereference'{module=CurrMod,type=EType} ->
1409	    F = lists:concat(["'",DecOrEnc,"_",EType,"'"]),
1410	    {F, "?MODULE", F};
1411	#'Externaltypereference'{module=Mod,type=EType} ->
1412	    {lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"]),Mod,
1413	     lists:concat(["'",DecOrEnc,"_",EType,"'"])};
1414	{constructed,bif} ->
1415	    F = lists:concat(["'",DecOrEnc,"_",asn1ct_gen:list2name([Cname|TopType]),"'"]),
1416	    {F, "?MODULE", F}
1417    end.
1418
1419mkfunname(TopType,Cname,WhatKind,DecOrEnc,Arity) ->
1420    CurrMod = get(currmod),
1421    case WhatKind of
1422	#'Externaltypereference'{module=CurrMod,type=EType} ->
1423	    F = lists:concat(["fun '",DecOrEnc,"_",EType,"'/",Arity]),
1424	    {F, "?MODULE", F};
1425	#'Externaltypereference'{module=Mod,type=EType} ->
1426	    {lists:concat(["{'",Mod,"','",DecOrEnc,"_",EType,"'}"]),Mod,
1427	     lists:concat(["'",DecOrEnc,"_",EType,"'"])};
1428	{constructed,bif} ->
1429	    F =
1430		lists:concat(["fun '",DecOrEnc,"_",
1431			      asn1ct_gen:list2name([Cname|TopType]),"'/",
1432			      Arity]),
1433	    {F, "?MODULE", F}
1434    end.
1435
1436empty_lb(ber) ->
1437    "[]";
1438empty_lb(ber_bin) ->
1439    "<<>>".
1440
1441rtmod(ber) ->
1442    list_to_atom(?RT_BER);
1443rtmod(ber_bin) ->
1444    list_to_atom(?RT_BER_BIN).
1445
1446indefend_match(ber,used_var) ->
1447    "[0,0|R]";
1448indefend_match(ber,unused_var) ->
1449    "[0,0|_R]";
1450indefend_match(ber_bin,used_var) ->
1451    "<<0,0,R/binary>>";
1452indefend_match(ber_bin,unused_var) ->
1453    "<<0,0,_R/binary>>".
1454
1455notice_value_match() ->
1456    Module = get(currmod),
1457    put(value_match,{true,Module}).
1458
1459value_match(Index,Value) when atom(Value) ->
1460    value_match(Index,atom_to_list(Value));
1461value_match([],Value) ->
1462    Value;
1463value_match([{VI,_Cname}|VIs],Value) ->
1464    value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
1465value_match1(Value,[],Acc,Depth) ->
1466    Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
1467value_match1(Value,[{VI,_Cname}|VIs],Acc,Depth) ->
1468    value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
1469