From a24997ac5526cb7cbb5f3248aaa4abd403bf406a Mon Sep 17 00:00:00 2001 From: Kenneth Lundin Date: Fri, 23 Mar 2012 12:21:03 +0100 Subject: Correct handling of INTEGER (1..4 | 8 | 10 | 20) --- lib/asn1/src/asn1ct.erl | 4 +- lib/asn1/src/asn1ct_check.erl | 88 +++++++++------------------- lib/asn1/test/asn1_SUITE_data/Constraints.py | 1 + lib/asn1/test/testConstraints.erl | 19 ++++-- 4 files changed, 47 insertions(+), 65 deletions(-) (limited to 'lib/asn1') diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 2d17f73a2c..99755a95a6 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -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}. diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index c223561f12..187339fb53 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -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), @@ -4467,63 +4467,33 @@ constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2= 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}, diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py index b18c29bd89..de48c4c2ca 100644 --- a/lib/asn1/test/asn1_SUITE_data/Constraints.py +++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py @@ -51,6 +51,7 @@ Thing ::= INTEGER {fred (0),fred2 (1),fred3 (2)} AnotherThing ::= Thing (fred | fred2) I ::= INTEGER (0|15..269) -- OTP-5457 +X1 ::= INTEGER (1..4 | 8 | 10 | 20) -- OTP-9946 -- OTP-5511 diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl index cb15a24359..1ce68ec522 100644 --- a/lib/asn1/test/testConstraints.erl +++ b/lib/asn1/test/testConstraints.erl @@ -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) -> -- cgit v1.2.3