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