~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_per.erl

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

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