Skip to content

Commit

Permalink
Merge branch 'kenneth/asn1/integer_range/OTP-9946' into maint
Browse files Browse the repository at this point in the history
* kenneth/asn1/integer_range/OTP-9946:
  replace 5 sec timeout (too short) with monitor in asn1_db requests
  Correct handling of INTEGER (1..4 | 8 | 10 | 20)
  • Loading branch information
KennethL committed Mar 29, 2012
2 parents e1dda02 + f2802b9 commit 6a3780b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 69 deletions.
16 changes: 12 additions & 4 deletions lib/asn1/src/asn1_db.erl
Expand Up @@ -48,11 +48,19 @@ dbstop() -> Resp = req(stop), erase(?MODULE), Resp.

%% Internal functions
req(Request) ->
get(?MODULE) ! {self(), Request},
receive {?MODULE, Reply} -> Reply after 5000 -> exit(db_timeout) end.
DbPid = get(?MODULE),
Ref = erlang:monitor(process,DbPid),
get(?MODULE) ! {{Ref, self()}, Request},
receive
{{Ref,?MODULE}, Reply} ->
erlang:demonitor(Ref,[flush]),
Reply;
{'DOWN',Ref,_,_,Info} ->
exit({db_error,Info})
end.

reply(From, Response) ->
From ! {?MODULE, Response}.
reply({Ref,From}, Response) ->
From ! {{Ref,?MODULE}, Response}.

init(Parent, Includes) ->
MRef = erlang:monitor(process, Parent),
Expand Down
4 changes: 3 additions & 1 deletion lib/asn1/src/asn1ct.erl
Expand Up @@ -816,7 +816,9 @@ check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
asn1_db:dbsave(DbFile,M#module.name),
verbose("--~p--~n",[{generated,DbFile}],Options),
{true,{M,NewM,GenTypeOrVal}}
end
end;
ErrorList = {error,_} ->
{false,ErrorList}
end;
check({false,M},_,_,_,_,_,_,_) ->
{false,M}.
Expand Down
88 changes: 29 additions & 59 deletions lib/asn1/src/asn1ct_check.erl
Expand Up @@ -4399,22 +4399,22 @@ constraint_union(_S,C) ->

constraint_union1(S,[A={'ValueRange',_},union,B={'ValueRange',_}|Rest],Acc) ->
AunionB = constraint_union_vr([A,B]),
constraint_union1(S,Rest,AunionB++Acc);
constraint_union1(S,Rest,Acc ++ AunionB);
constraint_union1(S,[A={'SingleValue',_},union,B={'SingleValue',_}|Rest],Acc) ->
AunionB = constraint_union_sv(S,[A,B]),
constraint_union1(S,Rest,AunionB++Acc);
constraint_union1(S,Rest,Acc ++ AunionB);
constraint_union1(S,[A={'SingleValue',_},union,B={'ValueRange',_}|Rest],Acc) ->
AunionB = union_sv_vr(S,A,B),
constraint_union1(S,Rest,AunionB++Acc);
constraint_union1(S,Rest,Acc ++ AunionB);
constraint_union1(S,[A={'ValueRange',_},union,B={'SingleValue',_}|Rest],Acc) ->
AunionB = union_sv_vr(S,B,A),
constraint_union1(S,Rest,AunionB++Acc);
constraint_union1(S,Rest,Acc ++ AunionB);
constraint_union1(S,[union|Rest],Acc) -> %skip when unsupported constraints
constraint_union1(S,Rest,Acc);
constraint_union1(S,[A|Rest],Acc) ->
constraint_union1(S,Rest,[A|Acc]);
constraint_union1(_S,[],Acc) ->
lists:reverse(Acc).
Acc.

constraint_union_sv(_S,SV) ->
Values=lists:map(fun({_,V})->V end,SV),
Expand Down Expand Up @@ -4467,63 +4467,33 @@ constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2=<Ub1->
constraint_union_vr([VR|Rest],Acc) ->
constraint_union_vr(Rest,[VR|Acc]).

union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',VR={Lb,Ub}})
union_sv_vr(_S,{'SingleValue',SV},VR)
when is_integer(SV) ->
case is_int_in_vr(SV,C2) of
true -> [C2];
_ ->
case VR of
{'MIN',Ub} when SV==Ub+1 -> [{'ValueRange',{'MIN',SV}}];
{Lb,'MAX'} when SV==Lb-1 -> [{'ValueRange',{SV,'MAX'}}];
{Lb,Ub} when SV==Ub+1 -> [{'ValueRange',{Lb,SV}}];
{Lb,Ub} when SV==Lb-1 -> [{'ValueRange',{SV,Ub}}];
_ ->
[C1,C2]
end
end;
union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',{_Lb,_Ub}})
union_sv_vr(_S,{'SingleValue',[SV]},VR);
union_sv_vr(_S,{'SingleValue',SV},{'ValueRange',{VLb,VUb}})
when is_list(SV) ->
case lists:filter(fun(X)->is_int_in_vr(X,C2) end,SV) of
[] -> [C2];
L ->
case expand_vr(L,C2) of
{[],C3} -> [C3];
{L,C2} -> [C1,C2];
{[Val],C3} -> [{'SingleValue',Val},C3];
{L2,C3} -> [{'SingleValue',L2},C3]
end
end.

expand_vr(L,VR={_,{Lb,Ub}}) ->
case lower_Lb(L,Lb) of
false ->
case higher_Ub(L,Ub) of
false ->
{L,VR};
{L1,UbNew} ->
expand_vr(L1,{'ValueRange',{Lb,UbNew}})
end;
{L1,LbNew} ->
expand_vr(L1,{'ValueRange',{LbNew,Ub}})
end.

lower_Lb(_,'MIN') ->
false;
lower_Lb(L,Lb) ->
remove_val_from_list(Lb - 1,L).

higher_Ub(_,'MAX') ->
false;
higher_Ub(L,Ub) ->
remove_val_from_list(Ub + 1,L).
L = lists:sort(SV++[VLb,VUb]),
{Lb,L1} = case lists:member('MIN',L) of
true -> {'MIN',L--['MIN']}; % remove 'MIN' so it does not disturb
false -> {hd(L),tl(L)}
end,
Ub = case lists:member('MAX',L1) of
true -> 'MAX';
false -> lists:last(L1)
end,
case SV of
[H] -> H;
_ -> SV
end,
%% for now we through away the Singlevalues so that they don't disturb
%% in the code generating phase (the effective Valuerange is already
%% calculated. If we want to keep the Singlevalues as well for
%% use in code gen phases we need to introduce a new representation
%% like {'ValueRange',{Lb,Ub},[ListOfRanges|AntiValues|Singlevalues]
%% These could be used to generate guards which allows only the specific
%% values , not the full range
[{'ValueRange',{Lb,Ub}}].

remove_val_from_list(Val,List) ->
case lists:member(Val,List) of
true ->
{lists:delete(Val,List),Val};
false ->
false
end.

%% get_constraints/2
%% Arguments are a list of constraints, which has the format {key,value},
Expand Down
1 change: 1 addition & 0 deletions lib/asn1/test/asn1_SUITE_data/Constraints.py
Expand Up @@ -51,6 +51,7 @@
AnotherThing ::= Thing (fred | fred2)

I ::= INTEGER (0|15..269) -- OTP-5457
X1 ::= INTEGER (1..4 | 8 | 10 | 20) -- OTP-9946

-- OTP-5511

Expand Down
19 changes: 14 additions & 5 deletions lib/asn1/test/testConstraints.erl
Expand Up @@ -127,17 +127,26 @@ int_constraints(Rules) ->
?line {ok,0} = asn1_wrapper:decode('Constraints','I',Bytes12),
?line {ok,Bytes13} = asn1_wrapper:encode('Constraints','I',20),
?line {ok,20} = asn1_wrapper:decode('Constraints','I',Bytes13),


%%==========================================================
%% Constraint Combinations (Duboisson p. 285)
%% X1 ::= INTEGER (1..4|8|10|20)
%%==========================================================

?line {ok,Bytes14} = asn1_wrapper:encode('Constraints','X1',1),
?line {ok,1} = asn1_wrapper:decode('Constraints','X1',Bytes14),
?line {ok,Bytes15} = asn1_wrapper:encode('Constraints','X1',20),
?line {ok,20} = asn1_wrapper:decode('Constraints','X1',Bytes15),
%%==========================================================
%% SIZE Constraint (Duboisson p. 268)
%% T ::= IA5String (SIZE (1|2, ..., SIZE (1|2|3)))
%% T2 ::= IA5String (SIZE (1|2, ..., 3))
%%==========================================================

?line {ok,Bytes14} = asn1_wrapper:encode('Constraints','T',"IA"),
?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T',Bytes14),
?line {ok,Bytes15} = asn1_wrapper:encode('Constraints','T2',"IA"),
?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T2',Bytes15).
?line {ok,Bytes16} = asn1_wrapper:encode('Constraints','T',"IA"),
?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T',Bytes16),
?line {ok,Bytes17} = asn1_wrapper:encode('Constraints','T2',"IA"),
?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T2',Bytes17).


refed_NNL_name(_Erule) ->
Expand Down

0 comments on commit 6a3780b

Please sign in to comment.