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