1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1997-2017. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% 21-module(asn1ct_constructed_per). 22 23-export([gen_encode_sequence/3]). 24-export([gen_decode_sequence/3]). 25-export([gen_encode_set/3]). 26-export([gen_decode_set/3]). 27-export([gen_encode_sof/4]). 28-export([gen_decode_sof/4]). 29-export([gen_encode_choice/3]). 30-export([gen_decode_choice/3]). 31 32-include("asn1_records.hrl"). 33 34-import(asn1ct_gen, [emit/1,get_record_name_prefix/1]). 35 36-type type_name() :: any(). 37 38 39%% ENCODE GENERATOR FOR SEQUENCE TYPE ** ********** 40 41 42-spec gen_encode_set(Gen, TypeName, #type{}) -> 'ok' when 43 Gen :: #gen{}, 44 TypeName :: type_name(). 45 46gen_encode_set(Gen, TypeName, D) -> 47 gen_encode_constructed(Gen, TypeName, D). 48 49-spec gen_encode_sequence(Gen, TypeName, #type{}) -> 'ok' when 50 Gen :: #gen{}, 51 TypeName :: type_name(). 52 53gen_encode_sequence(Gen, TypeName, D) -> 54 gen_encode_constructed(Gen, TypeName, D). 55 56gen_encode_constructed(Erule, Typename, #type{}=D) -> 57 asn1ct_name:start(), 58 Imm = gen_encode_constructed_imm(Erule, Typename, D), 59 asn1ct_imm:enc_cg(Imm, is_aligned(Erule)), 60 emit([".",nl]). 61 62gen_encode_constructed_imm(Gen, Typename, #type{}=D) -> 63 {CompList,TableConsInfo} = enc_complist(D), 64 ExternalImm = external_imm(Gen, Typename), 65 Optionals = optionals(to_textual_order(CompList)), 66 ImmOptionals = enc_optionals(Gen, Optionals), 67 Ext = extensible_enc(CompList), 68 Aligned = is_aligned(Gen), 69 ExtImm = case Ext of 70 {ext,ExtPos,NumExt} when NumExt > 0 -> 71 gen_encode_extaddgroup(Gen, CompList), 72 Value = make_var(val), 73 enc_extensions(Gen, Value, ExtPos, NumExt, Aligned); 74 _ -> 75 [] 76 end, 77 MatchImm = enc_map_match(Gen, CompList), 78 {EncObj,ObjSetImm} = enc_table(Gen, TableConsInfo, D), 79 ImmSetExt = 80 case Ext of 81 {ext,_Pos,NumExt2} when NumExt2 > 0 -> 82 asn1ct_imm:per_enc_extension_bit({var,"Extensions"}, Aligned); 83 {ext,_Pos,_} -> 84 asn1ct_imm:per_enc_extension_bit([], Aligned); 85 _ -> 86 [] 87 end, 88 ImmBody = gen_enc_components_call(Gen, Typename, CompList, EncObj, Ext), 89 ExternalImm ++ MatchImm ++ ExtImm ++ ObjSetImm ++ 90 asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody). 91 92external_imm(Gen, ['EXTERNAL']) -> 93 Next = asn1ct_gen:mk_var(asn1ct_name:next(val)), 94 Curr = asn1ct_gen:mk_var(asn1ct_name:curr(val)), 95 asn1ct_name:new(val), 96 F = case Gen of 97 #gen{pack=record} -> transform_to_EXTERNAL1990; 98 #gen{pack=map} -> transform_to_EXTERNAL1990_maps 99 end, 100 [{call,ext,F,[{var,Curr}],{var,Next}}]; 101external_imm(_, _) -> 102 []. 103 104enc_extensions(#gen{pack=record}, Value, ExtPos, NumExt, Aligned) -> 105 asn1ct_imm:per_enc_extensions(Value, ExtPos, NumExt, Aligned); 106enc_extensions(#gen{pack=map}, Value, ExtPos, NumExt, Aligned) -> 107 Vars = [{var,lists:concat(["Input@",Pos])} || 108 Pos <- lists:seq(ExtPos, ExtPos+NumExt-1)], 109 Undefined = atom_to_list(?MISSING_IN_MAP), 110 asn1ct_imm:per_enc_extensions_map(Value, Vars, Undefined, Aligned). 111 112enc_complist(#type{def=Def}) -> 113 case Def of 114 #'SEQUENCE'{tablecinf=TCI,components=CL0,extaddgroup=ExtAddGroup} -> 115 case ExtAddGroup of 116 undefined -> 117 {CL0,TCI}; 118 _ when is_integer(ExtAddGroup) -> 119 %% This is a fake SEQUENCE representing an 120 %% ExtensionAdditionGroup. Renumber the textual 121 %% order so we get the right index of the 122 %% components. 123 CL = add_textual_order(CL0), 124 {CL,TCI} 125 end; 126 #'SET'{tablecinf=TCI,components=CL} -> 127 {CL,TCI} 128 end. 129 130enc_table(Gen, #simpletableattributes{objectsetname=ObjectSet, 131 c_name=AttrN, 132 c_index=N, 133 usedclassfield=UniqueFieldName, 134 uniqueclassfield=UniqueFieldName, 135 valueindex=ValueIndex0}, _) -> 136 {Module,ObjSetName} = ObjectSet, 137 #typedef{typespec=#'ObjectSet'{gen=MustGen}} = 138 asn1_db:dbget(Module, ObjSetName), 139 case MustGen of 140 true -> 141 ValueIndex = ValueIndex0 ++ [{N+1,'ASN1_top'}], 142 Val = make_var(val), 143 {ObjSetImm,Dst} = enc_dig_out_value(Gen, ValueIndex, Val), 144 {{AttrN,Dst},ObjSetImm}; 145 false -> 146 {false,[]} 147 end; 148enc_table(_Gen, #simpletableattributes{}, _) -> 149 {false,[]}; 150enc_table(_Gen, _, #type{tablecinf=TCInf}) -> 151 case TCInf of 152 [{objfun,_}|_] -> 153 %% The simpletableattributes was at an outer 154 %% level and the objfun has been passed through the 155 %% function call. 156 {{"got objfun through args",{var,"ObjFun"}},[]}; 157 _ -> 158 {false,[]} 159 end. 160 161enc_optionals(Gen, Optionals) -> 162 Var = make_var(val), 163 enc_optionals_1(Gen, Optionals, Var). 164 165enc_optionals_1(#gen{pack=record}=Gen, [{Pos,DefVals}|T], Var) -> 166 {Imm0,Element} = asn1ct_imm:enc_element(Pos+1, Var), 167 Imm = asn1ct_imm:per_enc_optional(Element, DefVals), 168 [Imm0++Imm|enc_optionals_1(Gen, T, Var)]; 169enc_optionals_1(#gen{pack=map}=Gen, [{Pos,DefVals0}|T], V) -> 170 Var = {var,lists:concat(["Input@",Pos])}, 171 DefVals = translate_missing_value(Gen, DefVals0), 172 Imm = asn1ct_imm:per_enc_optional(Var, DefVals), 173 [Imm|enc_optionals_1(Gen, T, V)]; 174enc_optionals_1(_, [], _) -> 175 []. 176 177enc_map_match(#gen{pack=record}, _Cs) -> 178 []; 179enc_map_match(#gen{pack=map}, Cs0) -> 180 Var0 = "Input", 181 Cs = enc_flatten_components(Cs0), 182 M = [[quote_atom(Name),":=",lists:concat([Var0,"@",Order])] || 183 #'ComponentType'{prop=mandatory,name=Name, 184 textual_order=Order} <- Cs], 185 Mand = case M of 186 [] -> 187 []; 188 [_|_] -> 189 Patt = {expr,lists:flatten(["#{",lists:join(",", M),"}"])}, 190 [{assign,Patt,{var,asn1ct_name:curr(val)}}] 191 end, 192 193 Os0 = [{Name,Order} || 194 #'ComponentType'{prop=Prop,name=Name, 195 textual_order=Order} <- Cs, 196 Prop =/= mandatory], 197 {var,Val} = make_var(val), 198 F = fun({Name,Order}) -> 199 Var = lists:concat([Var0,"@",Order]), 200 P0 = ["case ",Val," of\n" 201 " #{",quote_atom(Name),":=",Var,"_0} -> ", 202 Var,"_0;\n" 203 " _ -> ",atom_to_list(?MISSING_IN_MAP),"\n" 204 "end"], 205 P = lists:flatten(P0), 206 {assign,{var,Var},P} 207 end, 208 Os = [F(O) || O <- Os0], 209 Mand ++ Os. 210 211enc_flatten_components({Root1,Ext0,Root2}=CL) -> 212 {_,Gs} = extgroup_pos_and_length(CL), 213 Ext = wrap_extensionAdditionGroups(Ext0, Gs), 214 Root1 ++ Root2 ++ [mark_optional(C) || C <- Ext]; 215enc_flatten_components({Root,Ext}) -> 216 enc_flatten_components({Root,Ext,[]}); 217enc_flatten_components(Cs) -> 218 Cs. 219 220gen_encode_extaddgroup(#gen{pack=record}, CompList) -> 221 case extgroup_pos_and_length(CompList) of 222 {extgrouppos,[]} -> 223 ok; 224 {extgrouppos,ExtGroupPosLenList} -> 225 _ = [gen_encode_eag_record(G) || 226 G <- ExtGroupPosLenList], 227 ok 228 end; 229gen_encode_extaddgroup(#gen{pack=map}, Cs0) -> 230 Cs = enc_flatten_components(Cs0), 231 gen_encode_eag_map(Cs). 232 233gen_encode_eag_map([#'ComponentType'{name=Group,typespec=Type}|Cs]) -> 234 case Type of 235 #type{def=#'SEQUENCE'{extaddgroup=G,components=GCs0}} 236 when is_integer(G) -> 237 Ns = [N || #'ComponentType'{name=N,prop=mandatory} <- GCs0], 238 test_for_mandatory(Ns, Group), 239 gen_encode_eag_map(Cs); 240 _ -> 241 gen_encode_eag_map(Cs) 242 end; 243gen_encode_eag_map([]) -> 244 ok. 245 246test_for_mandatory([Mand|_], Group) -> 247 emit([{next,val}," = case ",{curr,val}," of",nl, 248 "#{",quote_atom(Mand),":=_} -> ", 249 {curr,val},"#{",{asis,Group},"=>",{curr,val},"};",nl, 250 "#{} -> ",{curr,val},nl, 251 "end,",nl]), 252 asn1ct_name:new(val); 253test_for_mandatory([], _) -> 254 ok. 255 256gen_encode_eag_record({ActualPos,VirtualPos,Len}) -> 257 Val = asn1ct_gen:mk_var(asn1ct_name:curr(val)), 258 Elements = get_input_vars(Val, VirtualPos, Len), 259 Expr = any_non_value(Val, VirtualPos, Len), 260 emit([{next,val}," = case ",Expr," of",nl, 261 "false -> setelement(",{asis,ActualPos+1},", ", 262 {curr,val},", asn1_NOVALUE);",nl, 263 "true -> setelement(",{asis,ActualPos+1},", ", 264 {curr,val},", {extaddgroup,", Elements,"})",nl, 265 "end,",nl]), 266 asn1ct_name:new(val). 267 268any_non_value(Val, Pos, N) -> 269 L = any_non_value_1(Val, Pos, N), 270 lists:join(" orelse ", L). 271 272any_non_value_1(_, _, 0) -> 273 []; 274any_non_value_1(Val, Pos, N) -> 275 Var = get_input_var(Val, Pos), 276 [Var ++ " =/= asn1_NOVALUE"|any_non_value_1(Val, Pos+1, N-1)]. 277 278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 279%% generate decode function for SEQUENCE and SET 280%% 281gen_decode_set(Erules,Typename,D) -> 282 gen_decode_constructed(Erules,Typename,D). 283 284gen_decode_sequence(Erules,Typename,D) -> 285 gen_decode_constructed(Erules,Typename,D). 286 287gen_decode_constructed(Erule, Typename, #type{}=D) -> 288 Imm0 = gen_dec_constructed_imm(Erule, Typename, #type{}=D), 289 Imm = opt_imm(Imm0), 290 asn1ct_name:start(), 291 emit_gen_dec_imm(Imm), 292 emit([".",nl,nl]). 293 294opt_imm(Imm0) -> 295 {Imm,_} = opt_imm_1(Imm0, unknown, []), 296 Imm. 297 298opt_imm_1([{imm,Imm0,F}|T], Al0, Acc) -> 299 {Imm,Al} = asn1ct_imm:optimize_alignment(Imm0, Al0), 300 opt_imm_1(T, Al, [{imm,Imm,F}|Acc]); 301opt_imm_1([ignore|T], Al, Acc) -> 302 opt_imm_1(T, Al, Acc); 303opt_imm_1([{ignore,_}=H|T], Al, Acc) -> 304 opt_imm_1(T, Al, [H|Acc]); 305opt_imm_1([{safe,ignore}|T], Al, Acc) -> 306 opt_imm_1(T, Al, Acc); 307opt_imm_1([{safe,_}=H|T], Al, Acc) -> 308 opt_imm_1(T, Al, [H|Acc]); 309opt_imm_1([{group,G0}|T], Al0, Acc) -> 310 {G,Al} = opt_imm_1(G0, Al0, []), 311 opt_imm_1(T, Al, [{group,G}|Acc]); 312opt_imm_1([Emit|T], _, Acc) when is_function(Emit, 1) -> 313 opt_imm_1(T, unknown, [Emit|Acc]); 314opt_imm_1([], Al, Acc) -> 315 {lists:reverse(Acc),Al}. 316 317emit_gen_dec_imm(L) -> 318 emit_gen_dec_imm(L, "", []). 319 320emit_gen_dec_imm([{ignore,Fun}|T], Sep, St0) -> 321 St = Fun(St0), 322 emit_gen_dec_imm(T, Sep, St); 323emit_gen_dec_imm([{group,L}|T], Sep, St0) -> 324 emit(Sep), 325 St = emit_gen_dec_imm_group(L, St0), 326 emit_gen_dec_imm(T, [com,nl], St); 327emit_gen_dec_imm([{imm,Imm,Emit}|T], Sep, St0) -> 328 emit(Sep), 329 St = Emit(Imm, St0), 330 emit_gen_dec_imm(T, [com,nl], St); 331emit_gen_dec_imm([{safe,Item}|T], Sep, St) -> 332 emit_gen_dec_imm([Item|T], Sep, St); 333emit_gen_dec_imm([Emit|T], Sep, St0) -> 334 emit(Sep), 335 St = Emit(St0), 336 emit_gen_dec_imm(T, [com,nl], St); 337emit_gen_dec_imm([], _, _) -> ok. 338 339emit_gen_dec_imm_group([H|T], St0) -> 340 St = emit_gen_dec_group_item(H, St0), 341 emit_gen_dec_imm_group(T, St); 342emit_gen_dec_imm_group([], St) -> St. 343 344emit_gen_dec_group_item({ignore,Fun}, St) -> 345 Fun(St); 346emit_gen_dec_group_item({imm,Imm,Fun}, St) -> 347 Fun(Imm, St); 348emit_gen_dec_group_item({safe,Item}, St) -> 349 emit_gen_dec_group_item(Item, St); 350emit_gen_dec_group_item(Emit, St) -> 351 Emit(St). 352 353gen_dec_constructed_imm(Erule, Typename, #type{}=D) -> 354 {CompList,TableConsInfo} = 355 case D#type.def of 356 #'SEQUENCE'{tablecinf=TCI,components=CL} -> 357 {add_textual_order(CL),TCI}; 358 #'SET'{tablecinf=TCI,components=CL} -> 359 {CL,TCI} % the textual order is already taken care of 360 end, 361 Ext = extensible_dec(CompList), 362 EmitExt = case Ext of 363 {ext,_Pos,_NumExt} -> 364 gen_dec_extension_value(); 365 _ -> ignore 366 end, 367 Optionals = optionals(CompList), 368 EmitOpt = case Optionals of 369 [] -> 370 ignore; 371 [_|_] -> 372 gen_dec_optionals(Optionals) 373 end, 374 ObjSetInfo = 375 case TableConsInfo of 376 #simpletableattributes{objectsetname=ObjectSet, 377 c_name=AttrN, 378 usedclassfield=UniqueFieldName, 379 uniqueclassfield=UniqueFieldName, 380 valueindex=ValIndex} -> 381 F = fun(#'ComponentType'{typespec=CT})-> 382 case {asn1ct_gen:get_constraint(CT#type.constraint,componentrelation),CT#type.tablecinf} of 383 {no,[{objfun,_}|_R]} -> true; 384 _ -> false 385 end 386 end, 387 case lists:any(F,flat_complist(CompList)) of 388 true -> % when component relation constraint establish 389 %% relation from a component to another components 390 %% subtype component 391 {{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}}, 392 UniqueFieldName,ValIndex}; 393 false -> 394 {{AttrN,ObjectSet},UniqueFieldName,ValIndex} 395 end; 396 _ -> 397 case D#type.tablecinf of 398 [{objfun,_}|_] -> 399 {{"got objfun through args","ObjFun"},false,false}; 400 _ -> 401 {false,false,false} 402 end 403 end, 404 {DecObjInf,_,_} = ObjSetInfo, 405 EmitComp = gen_dec_components_call(Erule, Typename, CompList, 406 DecObjInf, Ext, length(Optionals)), 407 EmitObjSets = gen_dec_objsets_fun(Erule, ObjSetInfo), 408 EmitPack = fun(_) -> 409 gen_dec_pack(Erule, Typename, CompList) 410 end, 411 RestGroup = {group,[{safe,EmitObjSets},{safe,EmitPack}]}, 412 [EmitExt,EmitOpt|EmitComp++[RestGroup]]. 413 414gen_dec_objsets_fun(Gen, ObjSetInfo) -> 415 fun({AccTerm,AccBytes}) -> 416 {_,_UniqueFName,ValueIndex} = ObjSetInfo, 417 case {AccTerm,AccBytes} of 418 {[],[]} -> 419 ok; 420 {_,[]} -> 421 ok; 422 {[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} -> 423 ValueMatch = value_match(Gen, ValueIndex, Term), 424 _ = [begin 425 gen_dec_open_type(Gen, ValueMatch, ObjSet, 426 LeadingAttr, T), 427 emit([com,nl]) 428 end || T <- ListOfOpenTypes], 429 ok 430 end 431 end. 432 433gen_dec_pack(Gen, Typename, CompList) -> 434 case Typename of 435 ['EXTERNAL'] -> 436 dec_external(Gen, Typename); 437 _ -> 438 asn1ct_name:new(res), 439 gen_dec_do_pack(Gen, Typename, CompList), 440 emit([com,nl, 441 "{",{curr,res},",",{curr,bytes},"}"]) 442 end. 443 444dec_external(#gen{pack=record}=Gen, Typename) -> 445 RecordName = list_to_atom(record_name(Gen, Typename)), 446 All = [{var,Term} || Term <- asn1ct_name:all(term)], 447 Record = [{asis,RecordName}|All], 448 emit(["OldFormat={",lists:join(",", Record),"},",nl, 449 "ASN11994Format =",nl, 450 {call,ext,transform_to_EXTERNAL1994, 451 ["OldFormat"]},com,nl, 452 "{ASN11994Format,",{curr,bytes},"}"]); 453dec_external(#gen{pack=map}, _Typename) -> 454 Vars = asn1ct_name:all(term), 455 Names = ['direct-reference','indirect-reference', 456 'data-value-descriptor',encoding], 457 Zipped = lists:zip(Names, Vars), 458 MapInit = lists:join(",", [["'",N,"'=>",{var,V}] || {N,V} <- Zipped]), 459 emit(["OldFormat = #{",MapInit,"}",com,nl, 460 "ASN11994Format =",nl, 461 {call,ext,transform_to_EXTERNAL1994_maps, 462 ["OldFormat"]},com,nl, 463 "{ASN11994Format,",{curr,bytes},"}"]). 464 465gen_dec_do_pack(#gen{pack=record}=Gen, TypeName, CompList) -> 466 Zipped0 = zip_components(CompList, asn1ct_name:all(term)), 467 Zipped = textual_order(Zipped0), 468 RecordName = ["'",record_name(Gen, TypeName),"'"], 469 L = [RecordName|[{var,Var} || {_,Var} <- Zipped]], 470 emit([{curr,res}," = {",lists:join(",", L),"}"]); 471gen_dec_do_pack(#gen{pack=map}, _, CompList0) -> 472 CompList = enc_flatten_components(CompList0), 473 Zipped0 = zip_components(CompList, asn1ct_name:all(term)), 474 Zipped = textual_order(Zipped0), 475 PF = fun({#'ComponentType'{prop='OPTIONAL'},_}) -> false; 476 ({_,_}) -> true 477 end, 478 {Mandatory,Optional} = lists:partition(PF, Zipped), 479 L = [[{asis,Name},"=>",{var,Var}] || 480 {#'ComponentType'{name=Name},Var} <- Mandatory], 481 emit([{curr,res}," = #{",lists:join(",", L),"}"]), 482 gen_dec_map_optional(Optional), 483 gen_dec_merge_maps(asn1ct_name:all(map)). 484 485gen_dec_map_optional([{#'ComponentType'{name=Name},Var}|T]) -> 486 asn1ct_name:new(res), 487 emit([com,nl, 488 {curr,res}," = case ",{var,Var}," of",nl, 489 " asn1_NOVALUE -> ",{prev,res},";",nl, 490 " _ -> ",{prev,res},"#{",{asis,Name},"=>",{var,Var},"}",nl, 491 "end"]), 492 gen_dec_map_optional(T); 493gen_dec_map_optional([]) -> 494 ok. 495 496gen_dec_merge_maps([M|Ms]) -> 497 asn1ct_name:new(res), 498 emit([com,nl, 499 {curr,res}," = maps:merge(",{prev,res},", ",{var,M},")"]), 500 gen_dec_merge_maps(Ms); 501gen_dec_merge_maps([]) -> 502 ok. 503 504quote_atom(A) when is_atom(A) -> 505 io_lib:format("~p", [A]). 506 507%% record_name([TypeName]) -> RecordNameString 508%% Construct a record name for the constructed type, ignoring any 509%% fake sequences that are used to represent an extension addition 510%% group. Such fake sequences never appear as a top type, and their 511%% name always start with "ExtAddGroup". 512 513record_name(Gen, Typename0) -> 514 [TopType|Typename1] = lists:reverse(Typename0), 515 Typename = filter_ext_add_groups(Typename1, [TopType]), 516 lists:concat([get_record_name_prefix(Gen), 517 asn1ct_gen:list2rname(Typename)]). 518 519filter_ext_add_groups([H|T], Acc) when is_atom(H) -> 520 case atom_to_list(H) of 521 "ExtAddGroup"++_ -> 522 filter_ext_add_groups(T, Acc); 523 _ -> 524 filter_ext_add_groups(T, [H|Acc]) 525 end; 526filter_ext_add_groups([H|T], Acc) -> 527 filter_ext_add_groups(T, [H|Acc]); 528filter_ext_add_groups([], Acc) -> Acc. 529 530zip_components({Root,Ext}, Vars) -> 531 zip_components({Root,Ext,[]}, Vars); 532zip_components({R1,Ext0,R2}, Vars) -> 533 Ext = [mark_optional(C) || C <- Ext0], 534 zip_components(R1++R2++Ext, Vars); 535zip_components(Cs, Vars) when is_list(Cs) -> 536 zip_components_1(Cs, Vars). 537 538zip_components_1([#'ComponentType'{}=C|Cs], [V|Vs]) -> 539 [{C,V}|zip_components_1(Cs, Vs)]; 540zip_components_1([_|Cs], Vs) -> 541 zip_components_1(Cs, Vs); 542zip_components_1([], []) -> 543 []. 544 545textual_order([{#'ComponentType'{textual_order=undefined},_}|_]=L) -> 546 L; 547textual_order(L0) -> 548 L = [{Ix,P} || {#'ComponentType'{textual_order=Ix},_}=P <- L0], 549 [C || {_,C} <- lists:sort(L)]. 550 551to_textual_order({Root,Ext}) -> 552 {to_textual_order(Root),Ext}; 553to_textual_order(Cs) when is_list(Cs) -> 554 case Cs of 555 [#'ComponentType'{textual_order=undefined}|_] -> 556 Cs; 557 _ -> 558 lists:keysort(#'ComponentType'.textual_order,Cs) 559 end; 560to_textual_order(Cs) -> 561 Cs. 562 563gen_dec_open_type(Erule, Val, {Xmod,Xtype}, LeadingAttr, 564 {_,{Name,RestFieldNames},Term,TmpTerm,Prop}) -> 565 #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype), 566 #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0, 567 #'Externaltypereference'{module=ClMod,type=ClType} = Class, 568 #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType), 569 #objectclass{fields=ClassFields} = ClassDef, 570 Extensible = lists:member('EXTENSIONMARK', ObjSet1), 571 Typename = [Name,ClType], 572 ObjSet = index_object_set(Erule, ClType, Name, 573 ObjSet1, ClassFields), 574 Key = erlang:md5(term_to_binary({decode,ObjSet,RestFieldNames, 575 Prop,Extensible})), 576 Gen = fun(_Fd, N) -> 577 dec_objset_optional(N, Prop), 578 dec_objset(Erule, N, ObjSet, RestFieldNames, Typename), 579 dec_objset_default(N, Name, LeadingAttr, Extensible) 580 end, 581 Prefix = lists:concat(["dec_os_",Name]), 582 F = asn1ct_func:call_gen(Prefix, Key, Gen), 583 emit([Term," = ",{asis,F},"(",TmpTerm,", ",Val,")"]). 584 585dec_objset_optional(N, {'DEFAULT',Val}) -> 586 dec_objset_optional_1(N, Val); 587dec_objset_optional(N, 'OPTIONAL') -> 588 dec_objset_optional_1(N, asn1_NOVALUE); 589dec_objset_optional(_N, mandatory) -> ok. 590 591dec_objset_optional_1(N, Val) -> 592 emit([{asis,N},"(",{asis,Val},", _Id) ->",nl, 593 {asis,Val},";",nl]). 594 595dec_objset(_Erule, _N, [], _, _) -> 596 ok; 597dec_objset(Erule, N, [Obj|Objs], RestFields, Cl) -> 598 dec_objset_1(Erule, N, Obj, RestFields, Cl), 599 emit([";",nl]), 600 dec_objset(Erule, N, Objs, RestFields, Cl). 601 602dec_objset_default(N, C, LeadingAttr, false) -> 603 emit([{asis,N},"(Bytes, Id) ->",nl, 604 "exit({'Type not compatible with table constraint'," 605 "{{component,",{asis,C},"}," 606 "{value,Bytes}," 607 "{unique_name_and_value,",{asis,LeadingAttr},",Id}}}).",nl,nl]); 608dec_objset_default(N, _, _, true) -> 609 emit([{asis,N},"(Bytes, Id) ->",nl| 610 case asn1ct:use_legacy_types() of 611 false -> 612 ["{asn1_OPENTYPE,Bytes}.",nl,nl]; 613 true -> 614 ["Bytes.",nl,nl] 615 end]). 616 617dec_objset_1(Erule, N, {Id,Obj}, RestFields, Typename) -> 618 emit([{asis,N},"(Bytes, Id) when Id =:= ",{asis,Id}," ->",nl]), 619 dec_objset_2(Erule, Obj, RestFields, Typename). 620 621dec_objset_2(Erule, Obj, RestFields0, Typename) -> 622 case Obj of 623 #typedef{name={primitive,bif},typespec=Type} -> 624 Imm = asn1ct_gen_per:gen_dec_imm(Erule, Type), 625 {Term,_} = asn1ct_imm:dec_slim_cg(Imm, 'Bytes'), 626 emit([com,nl,Term]); 627 #typedef{name={constructed,bif},typespec=Type}=Def -> 628 Prefix = "dec_outlined_", 629 Key = {dec_outlined,Def}, 630 Gen = fun(_Fd, Name) -> 631 gen_dec_obj(Erule, Name, Typename, Type) 632 end, 633 Func = asn1ct_func:call_gen(Prefix, Key, Gen), 634 emit(["{Term,_} = ",{asis,Func},"(Bytes)",com,nl, 635 "Term"]); 636 #typedef{name=Type} -> 637 emit(["{Result,_} = ",{asis,enc_func("dec_", Type)},"(Bytes),",nl, 638 "Result"]); 639 #'Externaltypereference'{module=Mod,type=Type} -> 640 emit("{Term,_} = "), 641 Func = enc_func("dec_", Type), 642 case get(currmod) of 643 Mod -> 644 emit([{asis,Func},"(Bytes)"]); 645 _ -> 646 emit([{asis,Mod},":",{asis,Func},"(Bytes)"]) 647 end, 648 emit([com,nl, 649 "Term"]); 650 #'Externalvaluereference'{module=Mod,value=Value} -> 651 case asn1_db:dbget(Mod, Value) of 652 #typedef{typespec=#'Object'{def=Def}} -> 653 {object,_,Fields} = Def, 654 [NextField|RestFields] = RestFields0, 655 {NextField,Typedef} = lists:keyfind(NextField, 1, Fields), 656 dec_objset_2(Erule, Typedef, RestFields, Typename) 657 end 658 end. 659 660gen_dec_obj(Erules, Name, Typename, Type) -> 661 emit([{asis,Name},"(Bytes) ->",nl]), 662 InnerType = asn1ct_gen:get_inner(Type#type.def), 663 asn1ct_gen:gen_decode_constructed(Erules, Typename, 664 InnerType, Type). 665 666gen_encode_choice(Erule, TopType, D) -> 667 asn1ct_name:start(), 668 Imm = gen_encode_choice_imm(Erule, TopType, D), 669 asn1ct_imm:enc_cg(Imm, is_aligned(Erule)), 670 emit([".",nl]). 671 672gen_encode_choice_imm(Erule, TopType, #type{def={'CHOICE',CompList}}) -> 673 Ext = extensible_enc(CompList), 674 Aligned = is_aligned(Erule), 675 Cs = gen_enc_choice(Erule, TopType, CompList, Ext), 676 [{assign,{expr,"{ChoiceTag,ChoiceVal}"},"Val"}| 677 asn1ct_imm:per_enc_choice({var,"ChoiceTag"}, Cs, Aligned)]. 678 679gen_decode_choice(Erules,Typename,D) when is_record(D,type) -> 680 asn1ct_name:start(), 681 asn1ct_name:new(bytes), 682 {'CHOICE',CompList} = D#type.def, 683 Ext = extensible_enc(CompList), 684 gen_dec_choice(Erules,Typename,CompList,Ext), 685 emit([".",nl]). 686 687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 688%% Encode generator for SEQUENCE OF type 689 690gen_encode_sof(Erule, Typename, SeqOrSetOf, D) -> 691 asn1ct_name:start(), 692 Imm = gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, D), 693 asn1ct_imm:enc_cg(Imm, is_aligned(Erule)), 694 emit([".",nl,nl]). 695 696gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, #type{}=D) -> 697 {_SeqOrSetOf,ComponentType} = D#type.def, 698 Aligned = is_aligned(Erule), 699 CompType = ComponentType#type.def, 700 Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf, CompType), 701 Conttype = asn1ct_gen:get_inner(CompType), 702 Currmod = get(currmod), 703 Imm0 = case asn1ct_gen:type(Conttype) of 704 {primitive,bif} -> 705 asn1ct_gen_per:gen_encode_prim_imm({var,"Comp"}, 706 ComponentType, Aligned); 707 {constructed,bif} -> 708 TypeName = [Constructed_Suffix|Typename], 709 Enc = enc_func(asn1ct_gen:list2name(TypeName)), 710 ObjArg = case D#type.tablecinf of 711 [{objfun,_}|_] -> [{var,"ObjFun"}]; 712 _ -> [] 713 end, 714 [{apply,{local,Enc,CompType}, 715 [{var,"Comp"}|ObjArg]}]; 716 #'Externaltypereference'{module=Currmod,type=Ename} -> 717 [{apply,{local,enc_func(Ename),CompType},[{var,"Comp"}]}]; 718 #'Externaltypereference'{module=EMod,type=Ename} -> 719 [{apply,{EMod,enc_func(Ename),CompType},[{var,"Comp"}]}]; 720 'ASN1_OPEN_TYPE' -> 721 asn1ct_gen_per:gen_encode_prim_imm({var,"Comp"}, 722 #type{def='ASN1_OPEN_TYPE'}, 723 Aligned) 724 end, 725 asn1ct_imm:per_enc_sof({var,"Val"}, D#type.constraint, 'Comp', 726 Imm0, Aligned). 727 728gen_decode_sof(Erules, Typename, SeqOrSetOf, #type{}=D) -> 729 asn1ct_name:start(), 730 do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D), 731 emit([".",nl,nl]). 732 733do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D) -> 734 {_SeqOrSetOf,ComponentType} = D#type.def, 735 SizeConstraint = asn1ct_imm:effective_constraint(bitstring, 736 D#type.constraint), 737 ObjFun = 738 case D#type.tablecinf of 739 [{objfun,_}|_R] -> 740 ", ObjFun"; 741 _ -> 742 "" 743 end, 744 {Num,Buf} = gen_decode_length(SizeConstraint, Erules), 745 Key = erlang:md5(term_to_binary({Typename,SeqOrSetOf,ComponentType})), 746 Gen = fun(_Fd, Name) -> 747 gen_decode_sof_components(Erules, Name, 748 Typename, SeqOrSetOf, 749 ComponentType) 750 end, 751 F = asn1ct_func:call_gen("dec_components", Key, Gen), 752 emit([",",nl, 753 {asis,F},"(",Num,", ",Buf,ObjFun,", [])"]). 754 755is_aligned(#gen{erule=per,aligned=Aligned}) -> Aligned. 756 757gen_decode_length(Constraint, Erule) -> 758 emit(["%% Length with constraint ",{asis,Constraint},nl]), 759 Imm = asn1ct_imm:per_dec_length(Constraint, true, is_aligned(Erule)), 760 asn1ct_imm:dec_slim_cg(Imm, "Bytes"). 761 762gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont) -> 763 {ObjFun,ObjFun_Var} = 764 case Cont#type.tablecinf of 765 [{objfun,_}|_R] -> 766 {", ObjFun",", _"}; 767 _ -> 768 {"",""} 769 end, 770 emit([{asis,Name},"(0, Bytes",ObjFun_Var,", Acc) ->",nl, 771 "{lists:reverse(Acc),Bytes};",nl]), 772 emit([{asis,Name},"(Num, Bytes",ObjFun,", Acc) ->",nl, 773 "{Term,Remain} = "]), 774 Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf, 775 Cont#type.def), 776 Conttype = asn1ct_gen:get_inner(Cont#type.def), 777 case asn1ct_gen:type(Conttype) of 778 {primitive,bif} -> 779 asn1ct_gen_per:gen_dec_prim(Erule, Cont, "Bytes"), 780 emit([com,nl]); 781 {constructed,bif} -> 782 NewTypename = [Constructed_Suffix|Typename], 783 emit([{asis,dec_func(asn1ct_gen:list2name(NewTypename))}, 784 "(Bytes",ObjFun,"),",nl]); 785 #'Externaltypereference'{}=Etype -> 786 asn1ct_gen_per:gen_dec_external(Etype, "Bytes"), 787 emit([com,nl]); 788 'ASN1_OPEN_TYPE' -> 789 asn1ct_gen_per:gen_dec_prim(Erule, #type{def='ASN1_OPEN_TYPE'}, 790 "Bytes"), 791 emit([com,nl]); 792 _ -> 793 emit([{asis,dec_func(Conttype)},"(Bytes),",nl]) 794 end, 795 emit([{asis,Name},"(Num-1, Remain",ObjFun,", [Term|Acc]).",nl]). 796 797 798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 799%% General and special help functions (not exported) 800 801extensible_dec(CompList) when is_list(CompList) -> 802 noext; 803extensible_dec({RootList,ExtList}) -> 804 {ext,length(RootList)+1,ext_length(ExtList)}; 805extensible_dec({Rl1,Ext,Rl2}) -> 806 {ext,length(Rl1)+length(Rl2)+1,ext_length(Ext)}. 807 808extensible_enc(CompList) when is_list(CompList) -> 809 noext; 810extensible_enc({RootList,ExtList}) -> 811 {ext,length(RootList)+1,ext_length(ExtList)}; 812extensible_enc({Rl1,Ext,_Rl2}) -> 813 {ext,length(Rl1)+1,ext_length(Ext)}. 814 815ext_length(ExtList) -> ext_length(ExtList,normal,0). 816ext_length([{'ExtensionAdditionGroup',_Num}|T],_,Acc)-> 817 ext_length(T,group,Acc); 818ext_length(['ExtensionAdditionGroupEnd'|T],group,Acc) -> 819 ext_length(T,normal,Acc+1); 820ext_length([#'ComponentType'{}|T],State=group,Acc) -> 821 ext_length(T,State,Acc); 822ext_length([#'ComponentType'{}|T],State=normal,Acc) -> 823 ext_length(T,State,Acc+1); 824ext_length([],_,Acc) -> 825 Acc. 826 827extgroup_pos_and_length(CompList) when is_list(CompList) -> 828 {extgrouppos,[]}; 829extgroup_pos_and_length({RootList,ExtList}) -> 830 ActualPos = length(RootList) +1, 831 %% position to get and deliver data in the record to the user 832 VirtualPos = ActualPos, 833 %% position to encode/decode the extaddgroup as an opentype sequence 834 extgrouppos(ExtList,ActualPos,VirtualPos,[]); 835extgroup_pos_and_length({RootList,ExtList,_Rl2}) -> 836 extgroup_pos_and_length({RootList,ExtList}). 837 838extgrouppos([{'ExtensionAdditionGroup',_Num}|T],ActualPos,VirtualPos,Acc) -> 839 extgrouppos(T,ActualPos,VirtualPos,0,Acc); 840extgrouppos([_|T],ActualPos,VirtualPos,Acc) -> 841 extgrouppos(T,ActualPos+1,VirtualPos+1,Acc); 842extgrouppos([],_,_,Acc) -> 843 {extgrouppos,lists:reverse(Acc)}. 844 845extgrouppos(['ExtensionAdditionGroupEnd'|T],ActualPos,VirtualPos,Len,Acc) -> 846 extgrouppos(T,ActualPos+1,VirtualPos+Len,[{ActualPos,VirtualPos,Len}|Acc]); 847extgrouppos([_|T],ActualPos,VirtualPos,Len,Acc) -> 848 extgrouppos(T,ActualPos,VirtualPos,Len+1,Acc). 849 850 851gen_dec_extension_value() -> 852 Imm0 = {get_bits,1,[1]}, 853 E = fun(Imm, _) -> 854 emit(["{Ext,",{next,bytes},"} = "]), 855 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 856 asn1ct_imm:dec_code_gen(Imm, BytesVar), 857 asn1ct_name:new(bytes) 858 end, 859 {imm,Imm0,E}. 860 861gen_dec_optionals(Optionals) -> 862 Imm0 = {get_bits,length(Optionals),[1]}, 863 E = fun(Imm, _) -> 864 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 865 emit(["{Opt,",{next,bytes},"} = "]), 866 asn1ct_imm:dec_code_gen(Imm, BytesVar), 867 asn1ct_name:new(bytes) 868 end, 869 {imm,Imm0,E}. 870 871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 872 873optionals({Root1,Ext,Root2}) -> 874 Opt1 = optionals(Root1, 1), 875 ExtComps = length([C || C = #'ComponentType'{} <- Ext]), 876 Opt2 = optionals(Root2, 1 + length(Root1) + ExtComps), 877 Opt1 ++ Opt2; 878optionals({L,_Ext}) -> 879 optionals(L, 1); 880optionals(L) -> 881 optionals(L, 1). 882 883optionals([#'ComponentType'{prop='OPTIONAL'}|Rest], Pos) -> 884 [{Pos,[asn1_NOVALUE]}|optionals(Rest, Pos+1)]; 885optionals([#'ComponentType'{typespec=T,prop={'DEFAULT',Val}}|Cs], Pos) -> 886 Vals = def_values(T, Val), 887 [{Pos,Vals}|optionals(Cs, Pos+1)]; 888optionals([#'ComponentType'{}|Rest], Pos) -> 889 optionals(Rest, Pos+1); 890optionals([], _) -> 891 []. 892 893%%%%%%%%%%%%%%%%%%%%%% 894%% create_optionality_table(Cs=[#'ComponentType'{textual_order=undefined}|_]) -> 895%% {NewCs,_} = lists:mapfoldl(fun(C,Num) -> 896%% {C#'ComponentType'{textual_order=Num}, 897%% Num+1} 898%% end, 899%% 1,Cs), 900%% create_optionality_table(NewCs); 901create_optionality_table(Cs) -> 902 IsOptional = fun('OPTIONAL') -> true; 903 ({'DEFAULT',_}) -> true; 904 (_) -> false 905 end, 906 OptionalsElNum = [TO || #'ComponentType'{prop = O,textual_order=TO} <- Cs, 907 IsOptional(O)], 908 {Table,_} = lists:mapfoldl(fun(X,Num) -> 909 {{Num,X},Num+1} 910 end, 911 1,lists:sort(OptionalsElNum)), 912 Table. 913get_optionality_pos(TextPos,OptTable) -> 914 case lists:keysearch(TextPos,2,OptTable) of 915 {value,{OptNum,_}} -> 916 OptNum; 917 _ -> 918 no_num 919 end. 920 921add_textual_order(Cs) when is_list(Cs) -> 922 {NewCs,_} = add_textual_order1(Cs,1), 923 NewCs; 924add_textual_order({Root,Ext}) -> 925 {NewRoot,Num} = add_textual_order1(Root,1), 926 {NewExt,_} = add_textual_order1(Ext,Num), 927 {NewRoot,NewExt}; 928add_textual_order({R1,Ext,R2}) -> 929 {NewR1,Num1} = add_textual_order1(R1,1), 930 {NewExt,Num2} = add_textual_order1(Ext,Num1), 931 {NewR2,_} = add_textual_order1(R2,Num2), 932 {NewR1,NewExt,NewR2}. 933 934add_textual_order1(Cs,NumIn) -> 935 lists:mapfoldl(fun(C=#'ComponentType'{},Num) -> 936 {C#'ComponentType'{textual_order=Num}, 937 Num+1}; 938 (OtherMarker,Num) -> 939 {OtherMarker,Num} 940 end, 941 NumIn,Cs). 942 943gen_enc_components_call(Erule, TopType, {Root,ExtList}, DynamicEnc, Ext) -> 944 gen_enc_components_call(Erule, TopType, {Root,ExtList,[]}, DynamicEnc, Ext); 945gen_enc_components_call(Erule, TopType, {R1,ExtList0,R2}=CL, DynamicEnc, Ext) -> 946 Root = R1 ++ R2, 947 Imm0 = gen_enc_components_call1(Erule, TopType, Root, DynamicEnc, noext), 948 ExtImm = case Ext of 949 {ext,_,ExtNum} when ExtNum > 0 -> 950 [{var,"Extensions"}]; 951 _ -> 952 [] 953 end, 954 {extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL), 955 ExtList1 = wrap_extensionAdditionGroups(ExtList0, ExtGroupPosLen), 956 ExtList = [mark_optional(C) || C <- ExtList1], 957 Imm1 = gen_enc_components_call1(Erule, TopType, ExtList, DynamicEnc, Ext), 958 Imm0 ++ [ExtImm|Imm1]; 959gen_enc_components_call(Erule, TopType, CompList, DynamicEnc, Ext) -> 960 %% No extension marker. 961 gen_enc_components_call1(Erule, TopType, CompList, DynamicEnc, Ext). 962 963mark_optional(#'ComponentType'{prop=Prop0}=C) -> 964 Prop = case Prop0 of 965 mandatory -> 'OPTIONAL'; 966 'OPTIONAL'=Keep -> Keep; 967 {'DEFAULT',_}=Keep -> Keep 968 end, 969 C#'ComponentType'{prop=Prop}; 970mark_optional(Other) -> 971 Other. 972 973gen_enc_components_call1(Gen, TopType, [C|Rest], DynamicEnc, Ext) -> 974 #'ComponentType'{name=Cname,typespec=Type, 975 prop=Prop,textual_order=Num} = C, 976 InnerType = asn1ct_gen:get_inner(Type#type.def), 977 CommentString = attribute_comment(InnerType, Num, Cname), 978 ImmComment = asn1ct_imm:enc_comment(CommentString), 979 980 {Imm0,Element} = enc_fetch_field(Gen, Num, Prop), 981 Imm1 = gen_enc_line_imm(Gen, TopType, Cname, Type, 982 Element, DynamicEnc, Ext), 983 Imm2 = case Prop of 984 mandatory -> 985 Imm1; 986 'OPTIONAL' -> 987 enc_absent(Gen, Element, [asn1_NOVALUE], Imm1); 988 {'DEFAULT',Def} when Ext =:= noext -> 989 DefValues = def_values(Type, Def), 990 enc_absent(Gen, Element, DefValues, Imm1); 991 {'DEFAULT',_} -> 992 enc_absent(Gen, Element, [asn1_DEFAULT], Imm1) 993 end, 994 Imm = case Imm2 of 995 [] -> []; 996 _ -> [ImmComment|Imm0 ++ Imm2] 997 end, 998 [Imm|gen_enc_components_call1(Gen, TopType, Rest, DynamicEnc, Ext)]; 999gen_enc_components_call1(_Gen, _TopType, [], _, _) -> 1000 []. 1001 1002enc_absent(Gen, Var, Absent0, Imm) -> 1003 Absent = translate_missing_value(Gen, Absent0), 1004 asn1ct_imm:enc_absent(Var, Absent, Imm). 1005 1006translate_missing_value(#gen{pack=record}, Optionals) -> 1007 Optionals; 1008translate_missing_value(#gen{pack=map}, Optionals) -> 1009 case Optionals of 1010 [asn1_NOVALUE|T] -> [?MISSING_IN_MAP|T]; 1011 [asn1_DEFAULT|T] -> [?MISSING_IN_MAP|T]; 1012 {call,_,_,_} -> Optionals 1013 end. 1014 1015enc_fetch_field(#gen{pack=record}, Num, _Prop) -> 1016 Val = make_var(val), 1017 asn1ct_imm:enc_element(Num+1, Val); 1018enc_fetch_field(#gen{pack=map}, Num, _) -> 1019 {[],{var,lists:concat(["Input@",Num])}}. 1020 1021def_values(#type{def=#'Externaltypereference'{module=Mod,type=Type}}, Def) -> 1022 #typedef{typespec=T} = asn1_db:dbget(Mod, Type), 1023 def_values(T, Def); 1024def_values(#type{def={'BIT STRING',[]}}, Bs) when is_bitstring(Bs) -> 1025 case asn1ct:use_legacy_types() of 1026 false -> 1027 [asn1_DEFAULT,Bs]; 1028 true -> 1029 ListBs = [B || <<B:1>> <= Bs], 1030 IntBs = lists:foldl(fun(B, A) -> 1031 (A bsl 1) bor B 1032 end, 0, lists:reverse(ListBs)), 1033 Sz = bit_size(Bs), 1034 Compact = case 8 - Sz rem 8 of 1035 8 -> 1036 {0,Bs}; 1037 Unused -> 1038 {Unused,<<Bs:Sz/bits,0:Unused>>} 1039 end, 1040 [asn1_DEFAULT,Bs,Compact,ListBs,IntBs] 1041 end; 1042def_values(#type{def={'BIT STRING',[_|_]=Ns}}, List) when is_list(List) -> 1043 Bs = asn1ct_gen:named_bitstring_value(List, Ns), 1044 As = case asn1ct:use_legacy_types() of 1045 false -> 1046 [List,Bs]; 1047 true -> 1048 ListBs = [B || <<B:1>> <= Bs], 1049 IntBs = lists:foldl(fun(B, A) -> 1050 (A bsl 1) bor B 1051 end, 0, lists:reverse(ListBs)), 1052 [List,Bs,ListBs,IntBs] 1053 end, 1054 {call,per_common,is_default_bitstring,As}; 1055def_values(#type{def={'INTEGER',Ns}}, Def) -> 1056 [asn1_DEFAULT,Def|case lists:keyfind(Def, 2, Ns) of 1057 false -> []; 1058 {Val,Def} -> [Val] 1059 end]; 1060def_values(_, Def) -> 1061 [asn1_DEFAULT,Def]. 1062 1063gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext) -> 1064 Imm0 = gen_enc_line_imm_1(Erule, TopType, Cname, Type, 1065 Element, DynamicEnc), 1066 Aligned = is_aligned(Erule), 1067 case Ext of 1068 {ext,_Ep2,_} -> 1069 asn1ct_imm:per_enc_open_type(Imm0, Aligned); 1070 _ -> 1071 Imm0 1072 end. 1073 1074gen_enc_line_imm_1(Erule, TopType, Cname, Type, Element, DynamicEnc) -> 1075 Atype = 1076 case Type of 1077 #type{def=#'ObjectClassFieldType'{type=InnerType}} -> 1078 InnerType; 1079 _ -> 1080 asn1ct_gen:get_inner(Type#type.def) 1081 end, 1082 Aligned = is_aligned(Erule), 1083 case Atype of 1084 {typefield,_} -> 1085 {_LeadingAttrName,Fun} = DynamicEnc, 1086 case (Type#type.def)#'ObjectClassFieldType'.fieldname of 1087 {Name,RestFieldNames} when is_atom(Name) -> 1088 Imm = enc_var_type_call(Erule, Name, RestFieldNames, 1089 Type, Fun, Element), 1090 asn1ct_imm:per_enc_open_type(Imm, Aligned) 1091 end; 1092 _ -> 1093 CurrMod = get(currmod), 1094 case asn1ct_gen:type(Atype) of 1095 #'Externaltypereference'{module=CurrMod,type=EType} -> 1096 [{apply,{local,enc_func(EType),Atype},[Element]}]; 1097 #'Externaltypereference'{module=Mod,type=EType} -> 1098 [{apply,{Mod,enc_func(EType),Atype},[Element]}]; 1099 {primitive,bif} -> 1100 asn1ct_gen_per:gen_encode_prim_imm(Element, Type, Aligned); 1101 'ASN1_OPEN_TYPE' -> 1102 case Type#type.def of 1103 #'ObjectClassFieldType'{type=OpenType} -> 1104 asn1ct_gen_per:gen_encode_prim_imm(Element, 1105 #type{def=OpenType}, 1106 Aligned); 1107 _ -> 1108 asn1ct_gen_per:gen_encode_prim_imm(Element, 1109 Type, 1110 Aligned) 1111 end; 1112 {constructed,bif} -> 1113 NewTypename = [Cname|TopType], 1114 Enc = enc_func(asn1ct_gen:list2name(NewTypename)), 1115 case {Type#type.tablecinf,DynamicEnc} of 1116 {[{objfun,_}|_R],{_,EncFun}} -> 1117 [{apply,{local,Enc,Type},[Element,EncFun]}]; 1118 _ -> 1119 [{apply,{local,Enc,Type},[Element]}] 1120 end 1121 end 1122 end. 1123 1124enc_func(Type) -> 1125 enc_func("enc_", Type). 1126 1127enc_func(Prefix, Name) -> 1128 list_to_atom(lists:concat([Prefix,Name])). 1129 1130enc_var_type_call(Erule, Name, RestFieldNames, 1131 #type{tablecinf=TCI}, Fun, Val) -> 1132 [{objfun,#'Externaltypereference'{module=Xmod,type=Xtype}}] = TCI, 1133 #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype), 1134 #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0, 1135 #'Externaltypereference'{module=ClMod,type=ClType} = Class, 1136 #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType), 1137 #objectclass{fields=ClassFields} = ClassDef, 1138 Extensible = lists:member('EXTENSIONMARK', ObjSet1), 1139 ObjSet = index_object_set(Erule, ClType, Name, 1140 ObjSet1, ClassFields), 1141 Key = erlang:md5(term_to_binary({encode,ObjSet,RestFieldNames,Extensible})), 1142 TypeName = [ClType,Name], 1143 Imm = enc_objset_imm(Erule, TypeName, Name, ObjSet, 1144 RestFieldNames, Extensible), 1145 Lambda = {lambda,[{var,"Val"},{var,"Id"}],Imm}, 1146 Gen = fun(_Fd, N) -> 1147 Aligned = is_aligned(Erule), 1148 emit([{asis,N},"(Val, Id) ->",nl]), 1149 asn1ct_imm:enc_cg(Imm, Aligned), 1150 emit([".",nl]) 1151 end, 1152 Prefix = lists:concat(["enc_os_",Name]), 1153 [{call_gen,Prefix,Key,Gen,Lambda,[Val,Fun]}]. 1154 1155index_object_set(_Erules, _ClType, Name, Set0, ClassFields) -> 1156 Set = index_object_set_1(Name, Set0, ClassFields), 1157 lists:sort(Set). 1158 1159index_object_set_1(Name, [{_,Key,Code}|T], ClassFields) -> 1160 case index_object_set_2(Name, Code, ClassFields) of 1161 none -> 1162 index_object_set_1(Name, T, ClassFields); 1163 Type -> 1164 [{Key,Type}|index_object_set_1(Name, T, ClassFields)] 1165 end; 1166index_object_set_1(Name, [_|T], ClassFields) -> 1167 index_object_set_1(Name, T, ClassFields); 1168index_object_set_1(_, [], _) -> 1169 []. 1170 1171index_object_set_2(Name, [{Name,Type}|_], _ClassFields) -> 1172 Type; 1173index_object_set_2(Name, [_|T], ClassFields) -> 1174 index_object_set_2(Name, T, ClassFields); 1175index_object_set_2(Name, [], ClassFields) -> 1176 case lists:keyfind(Name, 2, ClassFields) of 1177 {typefield,Name,'OPTIONAL'} -> 1178 none; 1179 {objectfield,Name,_,_,'OPTIONAL'} -> 1180 none; 1181 {typefield,Name,{'DEFAULT',#type{}=Type}} -> 1182 InnerType = asn1ct_gen:get_inner(Type#type.def), 1183 case asn1ct_gen:type(InnerType) of 1184 {primitive,bif} -> 1185 #typedef{name={primitive,bif},typespec=Type}; 1186 {constructed,bif} -> 1187 #typedef{name={constructed,bif},typespec=Type} 1188 end 1189 end. 1190 1191enc_objset_imm(Erule, TypeName, Component, ObjSet, 1192 RestFieldNames, Extensible) -> 1193 Aligned = is_aligned(Erule), 1194 E = {error, 1195 fun() -> 1196 emit(["exit({'Type not compatible with table constraint'," 1197 "{component,",{asis,Component},"}," 1198 "{value,Val}," 1199 "{unique_name_and_value,'_'}})",nl]) 1200 end}, 1201 [{'cond', 1202 [[{eq,{var,"Id"},Key}| 1203 enc_obj(Erule, Obj, TypeName, RestFieldNames, Aligned)] || 1204 {Key,Obj} <- ObjSet] ++ 1205 [['_',case Extensible of 1206 false -> 1207 E; 1208 true -> 1209 case asn1ct:use_legacy_types() of 1210 false -> 1211 {call,per_common,open_type_to_binary, 1212 [{var,"Val"}]}; 1213 true -> 1214 {call,per_common,legacy_open_type_to_binary, 1215 [{var,"Val"}]} 1216 end 1217 end]]}]. 1218 1219enc_obj(Erule, Obj, TypeName, RestFieldNames0, Aligned) -> 1220 Val = {var,"Val"}, 1221 case Obj of 1222 #typedef{name={constructed,bif},typespec=Type}=Def -> 1223 Prefix = "enc_outlined_", 1224 Key = {enc_outlined,Def}, 1225 Gen = fun(_Fd, Name) -> 1226 gen_enc_obj(Erule, Name, TypeName, Type) 1227 end, 1228 [{call_gen,Prefix,Key,Gen,undefined,[Val]}]; 1229 #typedef{name={primitive,bif},typespec=Def} -> 1230 asn1ct_gen_per:gen_encode_prim_imm({var,"Val"}, Def, Aligned); 1231 #typedef{name=Type} -> 1232 [{apply,{local,enc_func(Type),Type},[{var,"Val"}]}]; 1233 #'Externalvaluereference'{module=Mod,value=Value} -> 1234 case asn1_db:dbget(Mod, Value) of 1235 #typedef{typespec=#'Object'{def=Def}} -> 1236 {object,_,Fields} = Def, 1237 [NextField|RestFieldNames] = RestFieldNames0, 1238 {NextField,Typedef} = lists:keyfind(NextField, 1, Fields), 1239 enc_obj(Erule, Typedef, TypeName, 1240 RestFieldNames, Aligned) 1241 end; 1242 #'Externaltypereference'{module=Mod,type=Type} -> 1243 Func = enc_func(Type), 1244 case get(currmod) of 1245 Mod -> 1246 [{apply,{local,Func,Obj},[{var,"Val"}]}]; 1247 _ -> 1248 [{apply,{Mod,Func,Obj},[{var,"Val"}]}] 1249 end 1250 end. 1251 1252gen_enc_obj(Erules, Name, Typename, Type) -> 1253 emit([{asis,Name},"(Val) ->",nl]), 1254 InnerType = asn1ct_gen:get_inner(Type#type.def), 1255 asn1ct_gen:gen_encode_constructed(Erules, Typename, 1256 InnerType, Type). 1257 1258gen_dec_components_call(Erule, TopType, {Root,ExtList}, 1259 DecInfObj, Ext, NumberOfOptionals) -> 1260 gen_dec_components_call(Erule,TopType,{Root,ExtList,[]}, 1261 DecInfObj,Ext,NumberOfOptionals); 1262gen_dec_components_call(Gen, TopType, {Root1,ExtList,Root2}=CL, 1263 DecInfObj, Ext, NumberOfOptionals) -> 1264 %% The type has extensionmarker 1265 OptTable = create_optionality_table(Root1++Root2), 1266 Init = {ignore,fun(_) -> {[],[]} end}, 1267 {EmitRoot,Tpos} = 1268 gen_dec_comp_calls(Root1++Root2, Gen, TopType, OptTable, 1269 DecInfObj, noext, NumberOfOptionals, 1270 1, []), 1271 EmitGetExt = gen_dec_get_extension(Gen), 1272 {extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL), 1273 NewExtList = wrap_extensionAdditionGroups(ExtList, ExtGroupPosLen), 1274 {EmitExts,_} = gen_dec_comp_calls(NewExtList, Gen, TopType, OptTable, 1275 DecInfObj, Ext, NumberOfOptionals, 1276 Tpos, []), 1277 NumExtsToSkip = ext_length(ExtList), 1278 Finish = 1279 fun(St) -> 1280 emit([{next,bytes},"= "]), 1281 Mod = case Gen of 1282 #gen{erule=per,aligned=false} -> uper; 1283 #gen{erule=per,aligned=true} -> per 1284 end, 1285 asn1ct_func:call(Mod, skipextensions, 1286 [{curr,bytes},NumExtsToSkip+1,"Extensions"]), 1287 asn1ct_name:new(bytes), 1288 St 1289 end, 1290 [Init] ++ EmitRoot ++ [EmitGetExt|EmitExts] ++ [Finish]; 1291gen_dec_components_call(Erule, TopType, CompList, DecInfObj, 1292 Ext, NumberOfOptionals) -> 1293 %% The type has no extensionmarker 1294 OptTable = create_optionality_table(CompList), 1295 Init = {ignore,fun(_) -> {[],[]} end}, 1296 {Cs,_} = gen_dec_comp_calls(CompList, Erule, TopType, OptTable, 1297 DecInfObj, Ext, NumberOfOptionals, 1298 1, []), 1299 [Init|Cs]. 1300 1301gen_dec_get_extension(Erule) -> 1302 Imm0 = asn1ct_imm:per_dec_extension_map(is_aligned(Erule)), 1303 E = fun(Imm, St) -> 1304 emit([nl,"%% Extensions", 1305 nl, 1306 "{Extensions,",{next,bytes},"} = ", 1307 "case Ext of",nl, 1308 "0 -> {<<>>,",{curr,bytes},"};",nl, 1309 "1 ->",nl]), 1310 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1311 {Dst,DstBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar), 1312 emit([com,nl, 1313 "{",Dst,",",DstBuf,"}",nl, 1314 "end"]), 1315 asn1ct_name:new(bytes), 1316 St 1317 end, 1318 {imm,Imm0,E}. 1319 1320gen_dec_comp_calls([C|Cs], Erule, TopType, OptTable, DecInfObj, 1321 Ext, NumberOfOptionals, Tpos, Acc) -> 1322 L = gen_dec_comp_call(C, Erule, TopType, Tpos, OptTable, DecInfObj, 1323 Ext, NumberOfOptionals), 1324 gen_dec_comp_calls(Cs, Erule, TopType, OptTable, DecInfObj, 1325 Ext, NumberOfOptionals, Tpos+1, [L|Acc]); 1326gen_dec_comp_calls([], _, _, _, _, _, _, Tpos, Acc) -> 1327 {lists:append(lists:reverse(Acc)),Tpos}. 1328 1329gen_dec_comp_call(Comp, Gen, TopType, Tpos, OptTable, DecInfObj, 1330 Ext, NumberOfOptionals) -> 1331 #'ComponentType'{name=Cname,typespec=Type, 1332 prop=Prop,textual_order=TextPos} = Comp, 1333 Pos = case Ext of 1334 noext -> Tpos; 1335 {ext,Epos,_Enum} -> Tpos - Epos + 1 1336 end, 1337 InnerType = asn1ct_gen:get_inner(Type#type.def), 1338 1339 CommentString = attribute_comment(InnerType, TextPos, Cname), 1340 Comment = fun(St) -> 1341 emit([nl,"%% ",CommentString,nl]), 1342 St 1343 end, 1344 1345 Preamble = 1346 case {InnerType,is_mandatory_predef_tab_c(Ext, Prop, DecInfObj)} of 1347 {{typefield,_},true} -> 1348 %% DecInfObj /= {"got objfun through args","ObjFun"} | 1349 %% (DecInfObj == {"got objfun through args","ObjFun"} & 1350 %% Ext == noext & Prop == mandatory) 1351 fun(St) -> 1352 asn1ct_name:new(term), 1353 asn1ct_name:new(tmpterm), 1354 emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]), 1355 St 1356 end; 1357 _ -> 1358 case Type of 1359 #type{def=#'SEQUENCE'{ 1360 extaddgroup=GroupNum, 1361 components=CompList}} when is_integer(GroupNum)-> 1362 dec_match_extadd_fun(Gen, CompList); 1363 _ -> 1364 fun(St) -> 1365 asn1ct_name:new(term), 1366 emit(["{",{curr,term}]), 1367 emit([",",{next,bytes},"} = "]), 1368 St 1369 end 1370 end 1371 end, 1372 {Pre,Post} = comp_call_pre_post(Gen, Ext, Prop, Pos, Type, TextPos, 1373 OptTable, NumberOfOptionals, Ext), 1374 Lines = gen_dec_seq_line_imm(Gen, TopType, Comp, Tpos, DecInfObj, Ext), 1375 AdvBuffer = {ignore,fun(St) -> 1376 asn1ct_name:new(bytes), 1377 St 1378 end}, 1379 [{group,[{safe,Comment},{safe,Preamble}] ++ Pre ++ 1380 Lines ++ Post ++ [{safe,AdvBuffer}]}]. 1381 1382dec_match_extadd_fun(#gen{pack=record}, CompList) -> 1383 fun(St) -> 1384 emit(["{{_,"]), 1385 emit_extaddgroupTerms(term, CompList), 1386 emit(["}"]), 1387 emit([",",{next,bytes},"} = "]), 1388 St 1389 end; 1390dec_match_extadd_fun(#gen{pack=map}, _CompList) -> 1391 fun(St) -> 1392 asn1ct_name:new(map), 1393 emit(["{",{curr,map},",",{next,bytes},"} = "]), 1394 St 1395 end. 1396 1397comp_call_pre_post(_Gen, noext, mandatory, _, _, _, _, _, _) -> 1398 {[],[]}; 1399comp_call_pre_post(_Gen, noext, Prop, _, Type, TextPos, 1400 OptTable, NumOptionals, Ext) -> 1401 %% OPTIONAL or DEFAULT 1402 OptPos = get_optionality_pos(TextPos, OptTable), 1403 Element = case NumOptionals - OptPos of 1404 0 -> 1405 "Opt band 1"; 1406 Shift -> 1407 lists:concat(["(Opt bsr ",Shift,") band 1"]) 1408 end, 1409 {[fun(St) -> 1410 emit(["case ",Element," of",nl, 1411 "1 ->",nl]), 1412 St 1413 end], 1414 [fun(St) -> 1415 emit([";",nl, 1416 "0 ->",nl, 1417 "{"]), 1418 gen_dec_component_no_val(Ext, Type, Prop), 1419 emit([",",{curr,bytes},"}",nl, 1420 "end"]), 1421 St 1422 end]}; 1423comp_call_pre_post(Gen, {ext,_,_}, Prop, Pos, Type, _, _, _, Ext) -> 1424 %% Extension 1425 {[fun(St) -> 1426 emit(["case Extensions of",nl, 1427 " <<_:",Pos-1,",1:1,_/bitstring>> ->",nl]), 1428 St 1429 end], 1430 [extadd_group_fun(Gen, Prop, Type, Ext)]}. 1431 1432extadd_group_fun(#gen{pack=record}, Prop, Type, Ext) -> 1433 fun(St) -> 1434 emit([";",nl, 1435 "_ ->",nl, 1436 "{"]), 1437 case Type of 1438 #type{def=#'SEQUENCE'{ 1439 extaddgroup=Number2, 1440 components=ExtGroupCompList2}} 1441 when is_integer(Number2)-> 1442 emit("{extAddGroup,"), 1443 gen_dec_extaddGroup_no_val(Ext, Type, ExtGroupCompList2), 1444 emit("}"); 1445 _ -> 1446 gen_dec_component_no_val(Ext, Type, Prop) 1447 end, 1448 emit([",",{curr,bytes},"}",nl, 1449 "end"]), 1450 St 1451 end; 1452extadd_group_fun(#gen{pack=map}, Prop, Type, Ext) -> 1453 fun(St) -> 1454 emit([";",nl, 1455 "_ ->",nl, 1456 "{"]), 1457 case Type of 1458 #type{def=#'SEQUENCE'{ 1459 extaddgroup=Number2, 1460 components=Comp}} 1461 when is_integer(Number2)-> 1462 dec_map_extaddgroup_no_val(Ext, Type, Comp); 1463 _ -> 1464 gen_dec_component_no_val(Ext, Type, Prop) 1465 end, 1466 emit([",",{curr,bytes},"}",nl, 1467 "end"]), 1468 St 1469 end. 1470 1471is_mandatory_predef_tab_c(noext, mandatory, 1472 {"got objfun through args","ObjFun"}) -> 1473 true; 1474is_mandatory_predef_tab_c(_, _, {"got objfun through args","ObjFun"}) -> 1475 false; 1476is_mandatory_predef_tab_c(_,_,_) -> 1477 true. 1478 1479gen_dec_extaddGroup_no_val(Ext, Type, [#'ComponentType'{prop=Prop}])-> 1480 gen_dec_component_no_val(Ext, Type, Prop), 1481 ok; 1482gen_dec_extaddGroup_no_val(Ext, Type, [#'ComponentType'{prop=Prop}|Rest])-> 1483 gen_dec_component_no_val(Ext, Type, Prop), 1484 emit(","), 1485 gen_dec_extaddGroup_no_val(Ext, Type, Rest); 1486gen_dec_extaddGroup_no_val(_, _, []) -> 1487 ok. 1488 1489gen_dec_component_no_val(_, Type, {'DEFAULT',DefVal0}) -> 1490 DefVal = asn1ct_gen:conform_value(Type, DefVal0), 1491 emit([{asis,DefVal}]); 1492gen_dec_component_no_val(_, _, 'OPTIONAL') -> 1493 emit(["asn1_NOVALUE"]); 1494gen_dec_component_no_val({ext,_,_}, _, mandatory) -> 1495 emit(["asn1_NOVALUE"]). 1496 1497dec_map_extaddgroup_no_val(Ext, Type, Comp) -> 1498 L0 = [dec_map_extaddgroup_no_val_1(N, P, Ext, Type) || 1499 #'ComponentType'{name=N,prop=P} <- Comp], 1500 L = [E || E <- L0, E =/= []], 1501 emit(["#{",lists:join(",", L),"}"]). 1502 1503dec_map_extaddgroup_no_val_1(Name, {'DEFAULT',DefVal0}, _Ext, Type) -> 1504 DefVal = asn1ct_gen:conform_value(Type, DefVal0), 1505 [Name,"=>",{asis,DefVal}]; 1506dec_map_extaddgroup_no_val_1(_Name, 'OPTIONAL', _, _) -> 1507 []; 1508dec_map_extaddgroup_no_val_1(_Name, mandatory, {ext,_,_}, _) -> 1509 []. 1510 1511gen_dec_choice_line(Erule, TopType, Comp, Pre) -> 1512 Imm0 = gen_dec_line_imm(Erule, TopType, Comp, false, Pre), 1513 Init = {ignore,fun(_) -> {[],[]} end}, 1514 Imm = [{group,[Init|Imm0]}], 1515 emit_gen_dec_imm(Imm). 1516 1517gen_dec_seq_line_imm(Erule, TopType, Comp, Pos, DecInfObj, Ext) -> 1518 Pre = gen_dec_line_open_type(Erule, Ext, Pos), 1519 gen_dec_line_imm(Erule, TopType, Comp, DecInfObj, Pre). 1520 1521gen_dec_line_imm(Erule, TopType, Comp, DecInfObj, Pre) -> 1522 #'ComponentType'{name=Cname,typespec=Type} = Comp, 1523 Atype = 1524 case Type of 1525 #type{def=#'ObjectClassFieldType'{type=InnerType}} -> 1526 InnerType; 1527 _ -> 1528 asn1ct_gen:get_inner(Type#type.def) 1529 end, 1530 Decode = gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj), 1531 Post = 1532 fun({SaveBytes,Finish}) -> 1533 {AccTerm,AccBytes} = Finish(), 1534 #'ComponentType'{name=Cname} = Comp, 1535 case DecInfObj of 1536 {Cname,ObjSet} -> 1537 ObjSetRef = 1538 case ObjSet of 1539 {deep,OSName,_,_} -> 1540 OSName; 1541 _ -> ObjSet 1542 end, 1543 {AccTerm++[{ObjSetRef,Cname, 1544 asn1ct_gen:mk_var(asn1ct_name:curr(term))}], 1545 AccBytes++SaveBytes}; 1546 _ -> 1547 {AccTerm,AccBytes++SaveBytes} 1548 end 1549 end, 1550 [Pre,Decode,{safe,Post}]. 1551 1552gen_dec_line_open_type(Erule, {ext,Ep,_}, Pos) when Pos >= Ep -> 1553 Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), 1554 {safe,fun(St) -> 1555 emit(["begin",nl]), 1556 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1557 {Dst,DstBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar), 1558 emit([",",nl,"{TmpValx",Pos,",_} = "]), 1559 {Dst, 1560 fun() -> 1561 emit([",",nl, 1562 "{TmpValx",Pos,",",DstBuf,"}",nl, 1563 "end"]), 1564 St 1565 end} 1566 end}; 1567gen_dec_line_open_type(_, _, _) -> 1568 {safe,fun(St) -> 1569 {asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1570 fun() -> St end} 1571 end}. 1572 1573gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp, 1574 DecInfObj) -> 1575 #'ComponentType'{name=Cname,typespec=Type,prop=Prop} = Comp, 1576 fun({_BytesVar,PrevSt}) -> 1577 case DecInfObj of 1578 false -> % This is in a choice with typefield components 1579 {Name,RestFieldNames} = 1580 (Type#type.def)#'ObjectClassFieldType'.fieldname, 1581 Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), 1582 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1583 {TmpTerm,TempBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar), 1584 emit([com,nl]), 1585 #type{tablecinf=[{objfun, 1586 #'Externaltypereference'{module=Xmod, 1587 type=Xtype}}]} = 1588 Type, 1589 gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype}, 1590 '_', {'_',{Name,RestFieldNames}, 1591 'Result',TmpTerm,mandatory}), 1592 emit([com,nl, 1593 "{",{asis,Cname},",{Result,",TempBuf,"}}"]), 1594 {[],PrevSt}; 1595 {"got objfun through args","ObjFun"} -> 1596 %% this is when the generated code gots the 1597 %% objfun though arguments on function 1598 %% invocation. 1599 if 1600 Prop =:= mandatory -> 1601 ok; 1602 true -> 1603 asn1ct_name:new(tmpterm), 1604 asn1ct_name:new(tmpbytes), 1605 emit([nl," {",{curr,tmpterm},", ",{curr,tmpbytes},"} ="]) 1606 end, 1607 {Name,RestFieldNames} = 1608 (Type#type.def)#'ObjectClassFieldType'.fieldname, 1609 Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), 1610 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1611 asn1ct_imm:dec_code_gen(Imm, BytesVar), 1612 emit([com,nl]), 1613 #type{tablecinf=[{objfun, 1614 #'Externaltypereference'{module=Xmod, 1615 type=Xtype}}]} = 1616 Type, 1617 Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)), 1618 TmpTerm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)), 1619 if 1620 Prop =:= mandatory -> 1621 gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype}, 1622 '_', {'_',{Name,RestFieldNames}, 1623 Term,TmpTerm,Prop}); 1624 true -> 1625 emit([" {"]), 1626 gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype}, 1627 '_', {'_',{Name,RestFieldNames}, 1628 '_',TmpTerm,Prop}), 1629 emit([",",nl,{curr,tmpbytes},"}"]) 1630 end, 1631 {[],PrevSt}; 1632 _ -> 1633 Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), 1634 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1635 asn1ct_imm:dec_code_gen(Imm, BytesVar), 1636 RefedFieldName = 1637 (Type#type.def)#'ObjectClassFieldType'.fieldname, 1638 1639 {[{Cname,RefedFieldName, 1640 asn1ct_gen:mk_var(asn1ct_name:curr(term)), 1641 asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)), 1642 Prop}],PrevSt} 1643 end 1644 end; 1645gen_dec_line_special(Gen, Atype, TopType, Comp, DecInfObj) -> 1646 case gen_dec_line_other(Gen, Atype, TopType, Comp) of 1647 Fun when is_function(Fun, 1) -> 1648 fun({BytesVar,PrevSt}) -> 1649 Fun(BytesVar), 1650 gen_dec_line_dec_inf(Gen,Comp, DecInfObj), 1651 {[],PrevSt} 1652 end; 1653 Imm0 -> 1654 {imm,Imm0, 1655 fun(Imm, {BytesVar,PrevSt}) -> 1656 asn1ct_imm:dec_code_gen(Imm, BytesVar), 1657 gen_dec_line_dec_inf(Gen, Comp, DecInfObj), 1658 {[],PrevSt} 1659 end} 1660 end. 1661 1662gen_dec_line_dec_inf(Gen, Comp, DecInfObj) -> 1663 #'ComponentType'{name=Cname} = Comp, 1664 case DecInfObj of 1665 {Cname,{_,_OSet,_UniqueFName,ValIndex}} -> 1666 Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)), 1667 ValueMatch = value_match(Gen, ValIndex,Term), 1668 emit([",",nl, 1669 "ObjFun = ",ValueMatch]); 1670 _ -> 1671 ok 1672 end. 1673 1674gen_dec_line_other(Erule, Atype, TopType, Comp) -> 1675 #'ComponentType'{name=Cname,typespec=Type} = Comp, 1676 case asn1ct_gen:type(Atype) of 1677 #'Externaltypereference'{}=Etype -> 1678 fun(BytesVar) -> 1679 asn1ct_gen_per:gen_dec_external(Etype, BytesVar) 1680 end; 1681 {primitive,bif} -> 1682 asn1ct_gen_per:gen_dec_imm(Erule, Type); 1683 'ASN1_OPEN_TYPE' -> 1684 case Type#type.def of 1685 #'ObjectClassFieldType'{type=OpenType} -> 1686 asn1ct_gen_per:gen_dec_imm(Erule, #type{def=OpenType}); 1687 _ -> 1688 asn1ct_gen_per:gen_dec_imm(Erule, Type) 1689 end; 1690 {constructed,bif} -> 1691 NewTypename = [Cname|TopType], 1692 DecFunc = dec_func(asn1ct_gen:list2name(NewTypename)), 1693 case Type#type.tablecinf of 1694 [{objfun,_}|_R] -> 1695 fun(BytesVar) -> 1696 emit([{asis,DecFunc},"(",BytesVar,", ObjFun)"]) 1697 end; 1698 _ -> 1699 fun(BytesVar) -> 1700 emit([{asis,DecFunc},"(",BytesVar,")"]) 1701 end 1702 end 1703 end. 1704 1705gen_enc_choice(Erule, TopType, {Root,Exts}, Ext) -> 1706 Constr = choice_constraint(Root), 1707 gen_enc_choices(Root, Erule, TopType, 0, Constr, Ext) ++ 1708 gen_enc_choices(Exts, Erule, TopType, 0, ext, Ext); 1709gen_enc_choice(Erule, TopType, {Root,Exts,[]}, Ext) -> 1710 gen_enc_choice(Erule, TopType, {Root,Exts}, Ext); 1711gen_enc_choice(Erule, TopType, Root, Ext) when is_list(Root) -> 1712 Constr = choice_constraint(Root), 1713 gen_enc_choices(Root, Erule, TopType, 0, Constr, Ext). 1714 1715choice_constraint(L) -> 1716 case length(L) of 1717 0 -> [{'SingleValue',0}]; 1718 Len -> [{'ValueRange',{0,Len-1}}] 1719 end. 1720 1721gen_enc_choices([H|T], Erule, TopType, Pos, Constr, Ext) -> 1722 #'ComponentType'{name=Cname,typespec=Type} = H, 1723 Aligned = is_aligned(Erule), 1724 EncObj = 1725 case asn1ct_gen:get_constraint(Type#type.constraint, 1726 componentrelation) of 1727 no -> 1728 case Type#type.tablecinf of 1729 [{objfun,_}|_] -> 1730 {"got objfun through args",{var,"ObjFun"}}; 1731 _ -> 1732 false 1733 end; 1734 _ -> 1735 {no_attr,{var,"ObjFun"}} 1736 end, 1737 DoExt = case Constr of 1738 ext -> Ext; 1739 _ -> noext 1740 end, 1741 Tag = case {Ext,Constr} of 1742 {noext,_} -> 1743 asn1ct_imm:per_enc_integer(Pos, Constr, Aligned); 1744 {{ext,_,_},ext} -> 1745 [{put_bits,1,1,[1]}| 1746 asn1ct_imm:per_enc_small_number(Pos, Aligned)]; 1747 {{ext,_,_},_} -> 1748 [{put_bits,0,1,[1]}| 1749 asn1ct_imm:per_enc_integer(Pos, Constr, Aligned)] 1750 end, 1751 Body = gen_enc_line_imm(Erule, TopType, Cname, Type, {var,"ChoiceVal"}, 1752 EncObj, DoExt), 1753 Imm = Tag ++ Body, 1754 [{Cname,Imm}|gen_enc_choices(T, Erule, TopType, Pos+1, Constr, Ext)]; 1755gen_enc_choices([], _, _, _, _, _) -> []. 1756 1757%% Generate the code for CHOICE. If the CHOICE is extensible, 1758%% the structure of the generated code is as follows: 1759%% 1760%% case Bytes of 1761%% <<0:1,Bytes1/bitstring>> -> 1762%% Choice = <Decode INTEGER (0..LastRootChoice) from Bytes1> 1763%% case Choice of 1764%% 0 -> <Decode>; 1765%% : 1766%% LastRootChoice -> <Decode> 1767%% end; 1768%% <<1:1,Bytes1/bitstring>> -> 1769%% Choice = <Decode normally small number from Bytes1> 1770%% TmpVal = <Decode open type> 1771%% case Choice of 1772%% 0 -> <Decode TmpVal>; 1773%% : 1774%% LastExtension -> <Decode TmpVal>; 1775%% _ -> <Return TmpVal since the type is unknown> 1776%% end 1777%% end 1778%% 1779%% The return value from the generated function always looks like: 1780%% {{ChoiceTag,Value},RemainingBuffer} 1781%% where ChoiceTag will be 'asn1_ExtAlt' for an unknown extension. 1782%% 1783%% If the CHOICE is not extensible, the top-level case is omitted 1784%% and only the code in the first case arm is generated. 1785 1786gen_dec_choice(Erule, TopType, CompList, {ext,_,_}=Ext) -> 1787 {RootList,ExtList} = split_complist(CompList), 1788 emit(["case Bytes of",nl]), 1789 case RootList of 1790 [] -> 1791 ok; 1792 [_|_] -> 1793 emit(["<<0:1,Bytes1/bitstring>> ->",nl]), 1794 asn1ct_name:new(bytes), 1795 gen_dec_choice1(Erule, TopType, RootList, noext), 1796 emit([";",nl,nl]) 1797 end, 1798 emit(["<<1:1,Bytes1/bitstring>> ->",nl]), 1799 asn1ct_name:clear(), 1800 asn1ct_name:new(bytes), 1801 asn1ct_name:new(bytes), 1802 gen_dec_choice1(Erule, TopType, ExtList, Ext), 1803 emit([nl,"end"]); 1804gen_dec_choice(Erule, TopType, CompList, noext) -> 1805 gen_dec_choice1(Erule, TopType, CompList, noext). 1806 1807split_complist({Root1,Ext,Root2}) -> 1808 {Root1++Root2,Ext}; 1809split_complist({_,_}=CompList) -> 1810 CompList. 1811 1812gen_dec_choice1(Erule, TopType, CompList, noext=Ext) -> 1813 emit_getchoice(Erule, CompList, Ext), 1814 emit(["case Choice of",nl]), 1815 Pre = {safe,fun(St) -> 1816 {asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1817 fun() -> St end} 1818 end}, 1819 gen_dec_choice2(Erule, TopType, CompList, Pre), 1820 emit([nl,"end"]); 1821gen_dec_choice1(Erule, TopType, CompList, {ext,_,_}=Ext) -> 1822 emit_getchoice(Erule, CompList, Ext), 1823 Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), 1824 emit(["begin",nl]), 1825 BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), 1826 {Dst,DstBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar), 1827 emit([nl, 1828 "end,",nl, 1829 "case Choice of",nl]), 1830 Pre = {safe,fun(St) -> 1831 emit(["{TmpVal,_} = "]), 1832 {Dst, 1833 fun() -> 1834 emit([",",nl, 1835 "{TmpVal,",DstBuf,"}"]), 1836 St 1837 end} 1838 end}, 1839 gen_dec_choice2(Erule, TopType, CompList, Pre), 1840 case CompList of 1841 [] -> ok; 1842 [_|_] -> emit([";",nl]) 1843 end, 1844 emit(["_ ->",nl, 1845 "{{asn1_ExtAlt,",Dst,"},",DstBuf,"}",nl, 1846 "end"]). 1847 1848emit_getchoice(Erule, CompList, Ext) -> 1849 Al = is_aligned(Erule), 1850 Imm = case {Ext,CompList} of 1851 {noext,[_]} -> 1852 {value,0}; 1853 {noext,_} -> 1854 asn1ct_imm:per_dec_constrained(0, length(CompList)-1, Al); 1855 {{ext,_,_},_} -> 1856 asn1ct_imm:per_dec_normally_small_number(Al) 1857 end, 1858 emit(["{Choice,",{curr,bytes},"} = ",nl]), 1859 BytesVar = asn1ct_gen:mk_var(asn1ct_name:prev(bytes)), 1860 asn1ct_imm:dec_code_gen(Imm, BytesVar), 1861 emit([com,nl]). 1862 1863gen_dec_choice2(Erule,TopType,L,Ext) -> 1864 gen_dec_choice2(Erule, TopType, L, 0, [], Ext). 1865 1866gen_dec_choice2(Erule, TopType, [H0|T], Pos, Sep0, Pre) -> 1867 #'ComponentType'{name=Cname,typespec=Type} = H0, 1868 H = H0#'ComponentType'{prop=mandatory}, 1869 emit([Sep0,Pos," ->",nl]), 1870 case Type#type.def of 1871 #'ObjectClassFieldType'{type={typefield,_}} -> 1872 emit("{Cname,{Val,NewBytes}} = begin\n"), 1873 gen_dec_choice_line(Erule, TopType, H, Pre), 1874 emit([nl, 1875 "end,",nl, 1876 "{{Cname,Val},NewBytes}"]); 1877 _ -> 1878 emit("{Val,NewBytes} = begin\n"), 1879 gen_dec_choice_line(Erule, TopType, H, Pre), 1880 emit([nl, 1881 "end,",nl, 1882 "{{",{asis,Cname},",Val},NewBytes}"]) 1883 end, 1884 Sep = [";",nl], 1885 gen_dec_choice2(Erule, TopType, T, Pos+1, Sep, Pre); 1886gen_dec_choice2(_, _, [], _, _, _) -> ok. 1887 1888get_input_vars(Val, I, N) -> 1889 L = get_input_vars_1(Val, I, N), 1890 lists:join(",", L). 1891 1892get_input_vars_1(_Val, _I, 0) -> 1893 []; 1894get_input_vars_1(Val, I, N) -> 1895 [get_input_var(Val, I)|get_input_vars_1(Val, I+1, N-1)]. 1896 1897get_input_var(Val, I) -> 1898 lists:flatten(io_lib:format("element(~w, ~s)", [I+1,Val])). 1899 1900emit_extaddgroupTerms(VarSeries,[_]) -> 1901 asn1ct_name:new(VarSeries), 1902 emit({curr,VarSeries}), 1903 ok; 1904emit_extaddgroupTerms(VarSeries,[_|Rest]) -> 1905 asn1ct_name:new(VarSeries), 1906 emit([{curr,VarSeries},","]), 1907 emit_extaddgroupTerms(VarSeries,Rest); 1908emit_extaddgroupTerms(_,[]) -> 1909 ok. 1910 1911flat_complist({Rl1,El,Rl2}) -> Rl1 ++ El ++ Rl2; 1912flat_complist({Rl,El}) -> Rl ++ El; 1913flat_complist(CompList) -> CompList. 1914 1915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1916%% Convert all componentTypes following 'ExtensionAdditionGroup' 1917%% up to the matching 'ExtensionAdditionGroupEnd' into one componentType 1918%% of type SEQUENCE with the componentTypes as components. 1919%% 1920wrap_extensionAdditionGroups(ExtCompList, ExtGroupPosLen) -> 1921 wrap_eags(ExtCompList, ExtGroupPosLen, 0, 0). 1922 1923wrap_eags([{'ExtensionAdditionGroup',_Number}|T0], 1924 [{ActualPos,_,_}|Gs], _ExtAddGroupDiff, ExtGroupNum) -> 1925 {ExtGroupCompList,['ExtensionAdditionGroupEnd'|T]} = 1926 lists:splitwith(fun(#'ComponentType'{}) -> true; 1927 (_) -> false 1928 end, T0), 1929 Name = list_to_atom(lists:concat(["ExtAddGroup",ExtGroupNum+1])), 1930 Seq = #type{def=#'SEQUENCE'{extaddgroup=ExtGroupNum+1, 1931 components=ExtGroupCompList}}, 1932 Comp = #'ComponentType'{name=Name, 1933 typespec=Seq, 1934 textual_order=ActualPos, 1935 prop='OPTIONAL'}, 1936 [Comp|wrap_eags(T, Gs, length(ExtGroupCompList)-1, ExtGroupNum+1)]; 1937wrap_eags([#'ComponentType'{textual_order=Tord}=H|T], 1938 ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum) 1939 when is_integer(Tord) -> 1940 Comp = H#'ComponentType'{textual_order=Tord - ExtAddGroupDiff}, 1941 [Comp|wrap_eags(T, ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum)]; 1942wrap_eags([H|T], ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum) -> 1943 [H|wrap_eags(T, ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum)]; 1944wrap_eags([], _, _, _) -> 1945 []. 1946 1947value_match(#gen{pack=record}, VIs, Value) -> 1948 value_match_rec(VIs, Value); 1949value_match(#gen{pack=map}, VIs, Value) -> 1950 value_match_map(VIs, Value). 1951 1952value_match_rec([], Value) -> 1953 Value; 1954value_match_rec([{VI,_}|VIs], Value0) -> 1955 Value = value_match_rec(VIs, Value0), 1956 lists:concat(["element(",VI,", ",Value,")"]). 1957 1958value_match_map([], Value) -> 1959 Value; 1960value_match_map([{_,Name}|VIs], Value0) -> 1961 Value = value_match_map(VIs, Value0), 1962 lists:concat(["maps:get(",Name,", ",Value,")"]). 1963 1964enc_dig_out_value(_Gen, [], Value) -> 1965 {[],Value}; 1966enc_dig_out_value(#gen{pack=record}=Gen, [{N,_}|T], Value) -> 1967 {Imm0,Dst0} = enc_dig_out_value(Gen, T, Value), 1968 {Imm,Dst} = asn1ct_imm:enc_element(N, Dst0), 1969 {Imm0++Imm,Dst}; 1970enc_dig_out_value(#gen{pack=map}, [{N,'ASN1_top'}], _Value) -> 1971 {[],{var,lists:concat(["Input@",N-1])}}; 1972enc_dig_out_value(#gen{pack=map}=Gen, [{_,Name}|T], Value) -> 1973 {Imm0,Dst0} = enc_dig_out_value(Gen, T, Value), 1974 {Imm,Dst} = asn1ct_imm:enc_maps_get(Name, Dst0), 1975 {Imm0++Imm,Dst}. 1976 1977make_var(Base) -> 1978 {var,atom_to_list(asn1ct_gen:mk_var(asn1ct_name:curr(Base)))}. 1979 1980attribute_comment(InnerType, TextPos, Cname) -> 1981 DispType = case InnerType of 1982 #'Externaltypereference'{type=T} -> T; 1983 IT when is_tuple(IT) -> element(2,IT); 1984 _ -> InnerType 1985 end, 1986 Comment = ["attribute ",Cname,"(",TextPos,") with type ",DispType], 1987 lists:concat(Comment). 1988 1989dec_func(Tname) -> 1990 list_to_atom(lists:concat(["dec_",Tname])). 1991