summaryrefslogtreecommitdiff
path: root/lib/asn1/src/asn1ct_imm.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1/src/asn1ct_imm.erl')
-rw-r--r--lib/asn1/src/asn1ct_imm.erl107
1 files changed, 79 insertions, 28 deletions
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index 231048694a..c2ec27e195 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -381,22 +381,44 @@ per_enc_optional(Val, {call,M,F,A}) ->
[[{eq,Tmp,true},Zero],['_',One]]}].
per_enc_sof(Val0, Constraint, ElementVar, ElementImm, Aligned) ->
- {B,[Val,Len]} = mk_vars(Val0, [len]),
- SzConstraint = effective_constraint(bitstring, Constraint),
- LenImm = enc_length(Len, SzConstraint, Aligned),
- Lc0 = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
- Lc = opt_lc(Lc0, LenImm),
- PreBlock = B ++ [{call,erlang,length,[Val],Len}],
- case LenImm of
- [{'cond',[[C|Action]]}] ->
- PreBlock ++ [{'cond',[[C|Action++Lc]]}];
- [{sub,_,_,_}=Sub,{'cond',[[C|Action]]}] ->
- PreBlock ++
- [Sub,{'cond',[[C|Action++Lc]]}];
- EncLen ->
- PreBlock ++ EncLen ++ Lc
+ case effective_constraint(bitstring, Constraint) of
+ no ->
+ per_enc_sof_fragmented(Val0, ElementVar, ElementImm, Aligned);
+ SzConstraint ->
+ {B,[Val,Len]} = mk_vars(Val0, [len]),
+ LenImm = enc_sof_length(Len, SzConstraint, Aligned),
+ Lc0 = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
+ Lc = opt_lc(Lc0, LenImm),
+ PreBlock = B ++ [{call,erlang,length,[Val],Len}],
+ case LenImm of
+ [{'cond',[[C|Action]]}] ->
+ PreBlock ++ [{'cond',[[C|Action++Lc]]}];
+ [{sub,_,_,_}=Sub,{'cond',[[C|Action]]}] ->
+ PreBlock ++
+ [Sub,{'cond',[[C|Action++Lc]]}];
+ EncLen ->
+ PreBlock ++ EncLen ++ Lc
+ end
end.
+per_enc_sof_fragmented(Val0, ElementVar, ElementImm, Aligned) ->
+ {B,[Val,Len,Fun]} = mk_vars(Val0, [len,fn]),
+ Lc = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
+ PreBlock = B ++ [{call,erlang,length,[Val],Len}],
+ U = unit(1, Aligned),
+ EncFragmented =
+ [{'fun',
+ [{var,atom_to_list(ElementVar)}],
+ ElementImm,
+ Fun},
+ {call,enc_mod(Aligned),encode_fragmented_sof,[Fun,Val,Len]}],
+ CondImm = build_cond([[{lt,Len,128},
+ {put_bits,Len,8,U}|Lc],
+ [{lt,Len,16384},
+ {put_bits,2,2,U},{put_bits,Len,14,[1]}|Lc],
+ ['_'|EncFragmented]]),
+ PreBlock ++ CondImm.
+
enc_absent(Val0, {call,M,F,A}, Body) ->
{B,[Var,Tmp]} = mk_vars(Val0, [tmp]),
B++[{call,M,F,[Var|A],Tmp},
@@ -586,7 +608,10 @@ decode_unconstrained_length(AllowZero, Aligned) ->
{value,{get_bits,7,[1|Zero]}}},
{test,{get_bits,1,[1|Al]},1,
{test,{get_bits,1,[1]},0,
- {value,{get_bits,14,[1|Zero]}}}}]}.
+ {value,{get_bits,14,[1|Zero]}}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},1,
+ {value,{mul,{get_bits,6,[1|Zero]},16384}}}}]}.
uper_num_bits(N) ->
uper_num_bits(N, 1, 0).
@@ -751,6 +776,9 @@ opt_al({value,E0}, A0) ->
opt_al({add,E0,I}, A0) when is_integer(I) ->
{E,A} = opt_al(E0, A0),
{{add,E,I},A};
+opt_al({mul,E0,I}, A0) when is_integer(I) ->
+ {E,A} = opt_al(E0, A0),
+ {{mul,E,I},A};
opt_al({test,E0,V,B0}, A0) ->
{E,A1} = opt_al(E0, A0),
{B,A2} = opt_al(B0, A1),
@@ -838,6 +866,10 @@ flatten({add,E0,I}, Buf0, St0) ->
{{Src,Buf},Pre,St1} = flatten(E0, Buf0, St0),
{Dst,St} = new_var("Add", St1),
{{Dst,Buf},Pre++[{add,Src,I,Dst}],St};
+flatten({mul,E0,I}, Buf0, St0) ->
+ {{Src,Buf},Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St} = new_var("Mul", St1),
+ {{Dst,Buf},Pre++[{mul,Src,I,Dst}],St};
flatten({'case',Cs0}, Buf0, St0) ->
{Dst,St1} = new_var_pair(St0),
{Cs1,St} = flatten_cs(Cs0, Buf0, St1),
@@ -951,6 +983,9 @@ dcg_list_outside([{'map',Val,Cs,Dst}|T]) ->
dcg_list_outside([{add,S1,S2,Dst}|T]) ->
emit([Dst," = ",S1," + ",S2]),
iter_dcg_list_outside(T);
+dcg_list_outside([{mul,S1,S2,Dst}|T]) ->
+ emit([Dst," = ",S1," * ",S2]),
+ iter_dcg_list_outside(T);
dcg_list_outside([{return,{V,Buf}}|T]) ->
emit(["{",V,",",Buf,"}"]),
iter_dcg_list_outside(T);
@@ -1055,6 +1090,7 @@ split_off_nonbuilding(Imm) ->
is_nonbuilding({assign,_,_}) -> true;
is_nonbuilding({call,_,_,_,_}) -> true;
is_nonbuilding({comment,_}) -> true;
+is_nonbuilding({'fun',_,_,_}) -> true;
is_nonbuilding({lc,_,_,_,_}) -> true;
is_nonbuilding({set,_,_}) -> true;
is_nonbuilding({list,_,_}) -> true;
@@ -1239,23 +1275,23 @@ per_enc_length(Bin, Unit0, Len, Sv, Aligned, Type) when is_integer(Sv) ->
Pb = {put_bits,Bin,binary,U},
[{'cond',[[{eq,Len,Sv},Pb]]}].
-enc_length(Len, no, Aligned) ->
+enc_sof_length(Len, no, Aligned) ->
U = unit(1, Aligned),
build_cond([[{lt,Len,128},
{put_bits,Len,8,U}],
[{lt,Len,16384},
{put_bits,2,2,U},{put_bits,Len,14,[1]}]]);
-enc_length(Len, {{Lb,Ub},[]}, Aligned) ->
+enc_sof_length(Len, {{Lb,Ub},[]}, Aligned) ->
{Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
NoExt = {put_bits,0,1,[1]},
- [{'cond',ExtConds0}] = enc_length(Len, no, Aligned),
+ [{'cond',ExtConds0}] = enc_sof_length(Len, no, Aligned),
Ext = {put_bits,1,1,[1]},
ExtConds = prepend_to_cond(ExtConds0, Ext),
build_length_cond(Prefix, [[Check,NoExt|PutLen]|ExtConds]);
-enc_length(Len, {Lb,Ub}, Aligned) when is_integer(Lb) ->
+enc_sof_length(Len, {Lb,Ub}, Aligned) when is_integer(Lb) ->
{Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
build_length_cond(Prefix, [[Check|PutLen]]);
-enc_length(Len, Sv, _Aligned) when is_integer(Sv) ->
+enc_sof_length(Len, Sv, _Aligned) when is_integer(Sv) ->
[{'cond',[[{eq,Len,Sv}]]}].
extensions_bitmap(Vs, Undefined) ->
@@ -1344,7 +1380,7 @@ eval_cond([[Cond|Actions]=H|T], Seen0) ->
eval_cond(T, Seen);
true ->
[['_'|Actions]];
- maybe ->
+ 'maybe' ->
[H|eval_cond(T, Seen)]
end;
true ->
@@ -1362,7 +1398,7 @@ eval_cond_1({ge,I,N}) when is_integer(I), is_integer(N) ->
I >= N;
eval_cond_1({lt,I,N}) when is_integer(I), is_integer(N) ->
I < N;
-eval_cond_1(_) -> maybe.
+eval_cond_1(_) -> 'maybe'.
prepend_to_cond([H|T], Code) ->
[prepend_to_cond_1(H, Code)|prepend_to_cond(T, Code)];
@@ -1730,6 +1766,9 @@ enc_make_cons({integer,Int}, {cons,{binary,H},T}) ->
enc_make_cons(H, T) ->
{cons,H,T}.
+enc_pre_cg_nonbuilding({'fun',Args,B0,Dst}, StL) ->
+ B = enc_pre_cg_1(B0, StL, outside_seq),
+ {'fun',Args,B,Dst};
enc_pre_cg_nonbuilding({lc,B0,Var,List,Dst}, StL) ->
B = enc_pre_cg_1(B0, StL, outside_seq),
{lc,B,Var,List,Dst};
@@ -1943,6 +1982,9 @@ enc_opt({cons,H0,T0}, St0) ->
{{cons,H,T},St#ost{t=t_cons(TypeH, TypeT)}};
enc_opt({error,_}=Imm, St) ->
{Imm,St#ost{t=t_any()}};
+enc_opt({'fun',_,_,Dst}=Imm, St0) ->
+ St = set_type(Dst, t_any(), St0),
+ {Imm,St};
enc_opt({integer,V}, St) ->
{{integer,subst(V, St)},St#ost{t=t_integer()}};
enc_opt({lc,E0,B,C}, St) ->
@@ -2067,7 +2109,7 @@ enc_opt_cs([{Cond,Imm0}|T], St0) ->
true ->
{Imm,#ost{t=Type}} = enc_opt(Imm0, St0),
[{'_',Imm,Type}];
- maybe ->
+ 'maybe' ->
St = update_type_info(Cond, St0),
{Imm,#ost{t=Type}} = enc_opt(Imm0, St),
[{Cond,Imm,Type}|enc_opt_cs(T, St0)]
@@ -2079,18 +2121,18 @@ eo_eval_cond('_', _) ->
eo_eval_cond({Op,{var,_}=Var,Val}, St) ->
Type = get_type(Var, St),
case t_range(Type) of
- any -> maybe;
+ any -> 'maybe';
{_,_}=Range -> eval_cond_range(Op, Range, Val)
end;
-eo_eval_cond({_Op,{expr,_},_Val}, _St) -> maybe.
+eo_eval_cond({_Op,{expr,_},_Val}, _St) -> 'maybe'.
eval_cond_range(lt, {Lb,Ub}, Val) ->
if
Ub < Val -> true;
Val =< Lb -> false;
- true -> maybe
+ true -> 'maybe'
end;
-eval_cond_range(_Op, _Range, _Val) -> maybe.
+eval_cond_range(_Op, _Range, _Val) -> 'maybe'.
update_type_info({ult,{var,_}=Var,Val}, St) ->
Int = t_integer({0,Val-1}),
@@ -2365,6 +2407,13 @@ enc_cg({error,Error}) when is_function(Error, 0) ->
enc_cg({error,{Tag,Var0}}) ->
Var = mk_val(Var0),
emit(["exit({error,{asn1,{",Tag,",",Var,"}}})"]);
+enc_cg({'fun',Args,Body,Dst0}) ->
+ Dst = mk_val(Dst0),
+ emit([Dst," = fun("]),
+ _ = [emit(mk_val(A)) || A <- Args],
+ emit(") -> "),
+ enc_cg(Body),
+ emit(" end");
enc_cg({integer,Int}) ->
emit(mk_val(Int));
enc_cg({lc,Body,Var,List}) ->
@@ -2738,6 +2787,8 @@ per_fixup([{call_gen,_,_,_,_,_}=H|T]) ->
[H|per_fixup(T)];
per_fixup([{error,_}=H|T]) ->
[H|per_fixup(T)];
+per_fixup([{'fun',Args,Body,Dst}|T]) ->
+ [{'fun',Args,per_fixup(Body),Dst}|per_fixup(T)];
per_fixup([{lc,B,V,L}|T]) ->
[{lc,per_fixup(B),V,L}|per_fixup(T)];
per_fixup([{lc,B,V,L,Dst}|T]) ->