diff options
author | Adam Lindberg <[email protected]> | 2012-01-12 15:42:21 +0100 |
---|---|---|
committer | Adam Lindberg <[email protected]> | 2012-02-28 14:59:32 +0100 |
commit | aa4e27ebac9eb287069fab859fe5dcdab82c75bf (patch) | |
tree | 7303d7d5f04c888a7934b783937ac2e3dc7f978a | |
parent | 93f0641c2122d6c23e2ac5f18579ef879599fc16 (diff) | |
download | otp-aa4e27ebac9eb287069fab859fe5dcdab82c75bf.tar.gz otp-aa4e27ebac9eb287069fab859fe5dcdab82c75bf.tar.bz2 otp-aa4e27ebac9eb287069fab859fe5dcdab82c75bf.zip |
[asn1] Make tables and processes unnamed
- Refactor and clean up asn1_db process
- Remove unused stop function in asn1ct.erl
- Remove infinite loop possibilites in asn1ct_check.erl
- test/1,2,3 now run in separate process
- Update documentation for new test options
-rw-r--r-- | lib/asn1/doc/src/asn1ct.xml | 94 | ||||
-rw-r--r-- | lib/asn1/src/asn1_db.erl | 257 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct.erl | 367 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_check.erl | 20 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_parser2.erl | 37 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_table.erl | 40 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_value.erl | 79 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE.erl.src | 36 | ||||
-rw-r--r-- | lib/asn1/test/testContextSwitchingTypes.erl | 9 | ||||
-rw-r--r-- | lib/asn1/test/testMegaco.erl | 8 | ||||
-rw-r--r-- | lib/asn1/test/test_inline.erl | 17 | ||||
-rw-r--r-- | lib/asn1/test/test_modified_x420.erl | 8 | ||||
-rw-r--r-- | lib/asn1/test/test_undecoded_rest.erl | 9 |
13 files changed, 517 insertions, 464 deletions
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index 0b9ec3df7f..3be58cbc8e 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2011</year> + <year>1997</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -44,15 +44,15 @@ </description> <funcs> <func> - <name>compile(Asn1module) -> ok | {error,Reason}</name> - <name>compile(Asn1module , Options) -> ok | {error,Reason}</name> + <name>compile(Asn1module) -> ok | {error, Reason}</name> + <name>compile(Asn1module, Options) -> ok | {error, Reason}</name> <fsummary>Compile an ASN.1 module and generate encode/decode functions according to the encoding rules BER or PER.</fsummary> <type> <v>Asn1module = atom() | string()</v> <v>Options = [Option| OldOption]</v> - <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string | - noobj | {n2n,EnumTypeName} |{outdir,Dir} | {i,IncludeDir} | optimize | - nif | asn1config | undec_rest | {inline,OutputName} | inline | + <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string | + noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} | optimize | + nif | asn1config | undec_rest | {inline, OutputName} | inline | {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v> <v>OldOption = ber | per</v> <v>Reason = term()</v> @@ -158,7 +158,7 @@ File3.asn </pre> of the BIT STRING type in Erlang. The notation: </p> <pre> -BitString = {Unused,Binary}, +BitString = {Unused, Binary}, Unused = integer(), Binary = binary() </pre> @@ -172,7 +172,7 @@ Binary = binary() </seealso>. </p> </item> - <tag><c>{n2n,EnumTypeName}</c></tag> + <tag><c>{n2n, EnumTypeName}</c></tag> <item> <p> Tells the compiler to generate functions for conversion between @@ -190,17 +190,17 @@ Binary = binary() <c>.erl</c> file. If this option is omitted the generated Erlang module will be compiled.</p> </item> - <tag><c>{i,IncludeDir}</c></tag> + <tag><c>{i, IncludeDir}</c></tag> <item> <p>Adds <c>IncludeDir</c> to the search-path for <c>.asn1db</c> and asn1 source files. The compiler tries to open a <c>.asn1db</c> file when a module imports definitions from another ASN.1 module. If no <c>.asn1db</c> file is found the asn1 source file is - parsed. Several <c>{i,IncludeDir}</c> can be given. + parsed. Several <c>{i, IncludeDir}</c> can be given. </p> </item> - <tag><c>{outdir,Dir}</c></tag> + <tag><c>{outdir, Dir}</c></tag> <item> <p>Specifies the directory <c>Dir</c> where all generated files shall be placed. If omitted the files are placed in the @@ -251,11 +251,11 @@ Binary = binary() also have some following bytes. Now it is possible to get those following bytes returned together with the decoded value. If an asn1 spec is compiled with this option a tuple - <c>{ok,Value,Rest}</c> is returned. <c>Rest</c> may be a + <c>{ok, Value, Rest}</c> is returned. <c>Rest</c> may be a list or a binary. Earlier versions of the compiler ignored those following bytes.</p> </item> - <tag><c>{inline,OutputName}</c></tag> + <tag><c>{inline, OutputName}</c></tag> <item> <p>Compiling with this option gives one output module containing all asn1 run-time functionality. The asn1 specs @@ -267,7 +267,7 @@ Binary = binary() by the <c>igor</c> module of <c>syntax_tools</c>. By default the functions generated from the first asn1 spec in the <c>.set.asn</c> are exported, unless a - <c>{export,[atom()]}</c> or <c>{export_all,true}</c> option + <c>{export, [atom()]}</c> or <c>{export_all, true}</c> option are provided. The list of atoms are names of chosen asn1 specs from the <c>.set.asn</c> file. </p> <p>When used together with <c>nif</c> for <c>ber_bin</c>, the @@ -278,7 +278,7 @@ Binary = binary() <tag><c>inline</c></tag> <item> <p>It is also possible to use the sole argument <c>inline</c>. - It is as <c>{inline,OutputName}</c>, but the output file gets the + It is as <c>{inline, OutputName}</c>, but the output file gets the default name of the source <c>.set.asn</c> file.</p> </item> <tag><c>{macro_name_prefix, Prefix}</c></tag> @@ -322,7 +322,7 @@ Binary = binary() </desc> </func> <func> - <name>encode(Module,Type,Value)-> {ok,Bytes} | {error,Reason}</name> + <name>encode(Module, Type, Value)-> {ok, Bytes} | {error, Reason}</name> <fsummary>Encode an ASN.1 value.</fsummary> <type> <v>Module = Type = atom()</v> @@ -337,13 +337,13 @@ Binary = binary() encode function only performs rudimentary tests that the input <c>Value</c> is a correct instance of <c>Type</c>. The length of strings is for example - not always checked. Returns <c>{ok,Bytes}</c> if successful or - <c>{error,Reason}</c> if an error occurred. + not always checked. Returns <c>{ok, Bytes}</c> if successful or + <c>{error, Reason}</c> if an error occurred. </p> </desc> </func> <func> - <name>decode(Module,Type,Bytes) -> {ok,Value}|{error,Reason}</name> + <name>decode(Module, Type, Bytes) -> {ok, Value} | {error, Reason}</name> <fsummary>Decode from Bytes into an ASN.1 value.</fsummary> <type> <v>Module = Type = atom()</v> @@ -352,11 +352,11 @@ Binary = binary() </type> <desc> <p>Decodes <c>Type</c> from <c>Module</c> from the list of bytes - <c>Bytes</c>. Returns <c>{ok,Value}</c> if successful.</p> + <c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p> </desc> </func> <func> - <name>value(Module ,Type) -> {ok,Value} | {error,Reason}</name> + <name>value(Module, Type) -> {ok, Value} | {error, Reason}</name> <fsummary>Create an ASN.1 value for test purposes.</fsummary> <type> <v>Module = Type = atom()</v> @@ -371,26 +371,48 @@ Binary = binary() </desc> </func> <func> - <name>test(Module) -> ok | {error,Reason}</name> - <name>test(Module,Type) -> ok | {error,Reason}</name> - <name>test(Module,Type,Value) -> ok | {error,Reason}</name> - <fsummary>Perform a test of encode and decode for types in an ASN.1 module.</fsummary> + <name>test(Module) -> ok | {error, Reason}</name> + <name>test(Module, Type | Options) -> ok | {error, Reason}</name> + <name>test(Module, Type, Value | Options) -> ok | {error, Reason}</name> + <fsummary>Perform a test of encode and decode for types in an ASN.1 module.</fsummary> + <type> + <v>Module = Type = atom()</v> + <v>Value = term()</v> + <v>Options = [{i, IncludeDir}]</v> + <v>Reason = term()</v> + </type> <desc> - <p>Performs a test of encode and decode of all types in <c>Module</c>. + <p>Performs a test of encode and decode of types in <c>Module</c>. The generated functions are called by this function. This function is useful during test to secure that the generated - encode and decode functions and the general runtime support work - as expected. <br></br> -<c>test/1</c> iterates over all types in <c>Module</c>. <br></br> -<c>test/2</c> tests type <c>Type</c> with a random value. <br></br> -<c><![CDATA[test/3 tests type <c>Type]]></c> with <c>Value</c>. <br></br> + encode and decode functions and the general runtime support work + as expected.</p> + + <list type="bulleted"> + <item> + <p><c>test/1</c> iterates over all types in <c>Module</c>.</p> + </item> + <item> + <p><c>test/2</c> tests type <c>Type</c> with a random value.</p> + </item> + <item> + <p><c>test/3</c> tests type <c>Type</c> with <c>Value</c>.</p> + </item> + </list> - Schematically the following happens for each type in the module.</p> - <p></p> + <p>Schematically the following happens for each type in the module: <code type="none"> -{ok,Value} = asn1ct:value(Module,Type), -{ok,Bytes} = asn1ct:encode(Module,Type,Value), -{ok,Value} = asn1ct:decode(Module,Type,Bytes). </code> +{ok, Value} = asn1ct:value(Module, Type), +{ok, Bytes} = asn1ct:encode(Module, Type, Value), +{ok, Value} = asn1ct:decode(Module, Type, Bytes).</code></p> + + <p>The <c>test</c> functions utilizes the <c>*.asn1db</c> files + for all included modules. If they are located in a different + directory than the current working directory, use the include + option to add paths. This is only needed when automatically + generating values. For static values using <c>Value</c> no + options are needed.</p> + </desc> </func> </funcs> diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl index f680b3d064..0862ef6e02 100644 --- a/lib/asn1/src/asn1_db.erl +++ b/lib/asn1/src/asn1_db.erl @@ -1,167 +1,146 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% -module(asn1_db). -%-compile(export_all). --export([dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]). --export([dbget_all_mod/1,dbstop/0,dbclear/0,dberase_module/1,dbstart/1,stop_server/1]). -%% internal exports --export([dbloop0/1,dbloop/2]). -%% Db stuff -dbstart(Includes) -> - start_server(asn1db, asn1_db, dbloop0, [Includes]). +-export([dbstart/1,dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]). +-export([dbget_all_mod/1,dbclear/0,dberase_module/1,dbstop/0]). -dbloop0(Includes) -> - dbloop(Includes, ets:new(asn1, [set,named_table])). - -opentab(Tab,Mod,[]) -> - opentab(Tab,Mod,["."]); -opentab(Tab,Mod,Includes) -> - Base = lists:concat([Mod,".asn1db"]), - opentab2(Tab,Base,Mod,Includes,ok). +-record(state, {parent, monitor, includes, table}). -opentab2(_Tab,_Base,_Mod,[],Error) -> - Error; -opentab2(Tab,Base,Mod,[Ih|It],_Error) -> - File = filename:join(Ih,Base), - case ets:file2tab(File) of - {ok,Modtab} -> - ets:insert(Tab,{Mod, Modtab}), - {ok,Modtab}; - NewErr -> - opentab2(Tab,Base,Mod,It,NewErr) +%% Interface +dbstart(Includes) -> + Parent = self(), + case get(?MODULE) of + undefined -> + put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)), + true; + _Pid -> + req({new_includes, Includes}) end. - -dbloop(Includes, Tab) -> +dbnew(Module) -> req({new, Module}). +dbsave(OutFile, Module) -> req({save, OutFile, Module}). +dbload(Module) -> req({load, Module}). +dbput(Module, K, V) -> req({set, Module, K, V}). +dbget(Module, K) -> req({get, Module, K}). +dbget_all(K) -> req({get_all, K}). +dbget_all_mod(Mod) -> req({all_mod, Mod}). +dbclear() -> req(clear). +dberase_module({module,M}) -> req({delete_mod, M}). +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. + +reply(From, Response) -> + From ! {?MODULE, Response}. + +init(Parent, Includes) -> + MRef = erlang:monitor(process, Parent), + loop(#state{parent = Parent, monitor = MRef, includes = Includes, + table = ets:new(?MODULE, [])}). + +loop(#state{parent = Parent, monitor = MRef, table = Table, + includes = Includes} = State) -> receive - {From,{set, Mod, K2, V}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - ets:insert(Modtab,{K2, V}), - From ! {asn1db, ok}, - dbloop(Includes, Tab); - {From, {get, Mod, K2}} -> - Result = case ets:lookup(Tab,Mod) of - [] -> - opentab(Tab,Mod,Includes); - [{_,Modtab}] -> {ok,Modtab} - end, - case Result of - {ok,Newtab} -> - From ! {asn1db, lookup(Newtab, K2)}; - _Error -> - From ! {asn1db, undefined} - end, - dbloop(Includes, Tab); - {From, {all_mod, Mod}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - From ! {asn1db, ets:tab2list(Modtab)}, - dbloop(Includes, Tab); - {From, {delete_mod, Mod}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - ets:delete(Modtab), - ets:delete(Tab,Mod), - From ! {asn1db, ok}, - dbloop(Includes, Tab); - {From, {save, OutFile,Mod}} -> - [{_,Mtab}] = ets:lookup(Tab,Mod), - From ! {asn1db, ets:tab2file(Mtab,OutFile)}, - dbloop(Includes,Tab); - {From, {load, Mod}} -> - Result = case ets:lookup(Tab,Mod) of - [] -> - opentab(Tab,Mod,Includes); - [{_,Modtab}] -> {ok,Modtab} - end, - From ! {asn1db,Result}, - dbloop(Includes,Tab); - {From, {new, Mod}} -> - case ets:lookup(Tab,Mod) of - [{_,Modtab}] -> - ets:delete(Modtab); - _ -> - true - end, - Tabname = list_to_atom(lists:concat(["asn1_",Mod])), - ets:new(Tabname, [set,named_table]), - ets:insert(Tab,{Mod,Tabname}), - From ! {asn1db, ok}, - dbloop(Includes,Tab); - {From, stop} -> - From ! {asn1db, ok}; %% nothing to store - {From, clear} -> - ModTabList = [Mt||{_,Mt} <- ets:tab2list(Tab)], - lists:foreach(fun(T) -> ets:delete(T) end,ModTabList), - ets:delete(Tab), - From ! {asn1db, cleared}, - dbloop(Includes, ets:new(asn1, [set])); - {From,{new_includes,[NewIncludes]}} -> - From ! {asn1db,done}, - dbloop(NewIncludes,Tab) + {From, {set, Mod, K2, V}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + ets:insert(Modtab, {K2, V}), + reply(From, ok), + loop(State); + {From, {get, Mod, K2}} -> + Result = case ets:lookup(Table, Mod) of + [] -> opentab(Table, Mod, Includes); + [{_, Modtab}] -> {ok, Modtab} + end, + case Result of + {ok, Newtab} -> reply(From, lookup(Newtab, K2)); + _Error -> reply(From, undefined) + end, + loop(State); + {From, {all_mod, Mod}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + reply(From, ets:tab2list(Modtab)), + loop(State); + {From, {delete_mod, Mod}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + ets:delete(Modtab), + ets:delete(Table, Mod), + reply(From, ok), + loop(State); + {From, {save, OutFile, Mod}} -> + [{_,Mtab}] = ets:lookup(Table, Mod), + reply(From, ets:tab2file(Mtab, OutFile)), + loop(State); + {From, {load, Mod}} -> + Result = case ets:lookup(Table, Mod) of + [] -> opentab(Table, Mod, Includes); + [{_, Modtab}] -> {ok, Modtab} + end, + reply(From, Result), + loop(State); + {From, {new, Mod}} -> + case ets:lookup(Table, Mod) of + [{_, Modtab}] -> ets:delete(Modtab); + _ -> true + end, + ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []), + ets:insert(Table, {Mod, ModTableId}), + reply(From, ok), + loop(State); + {From, clear} -> + [ets:delete(Mt) || {_, Mt} <- ets:tab2list(Table)], + ets:delete(Table), + reply(From, cleared), + loop(State#state{table = ets:new(asn1, [set])}); + {From, {new_includes, NewIncludes}} -> + reply(From, true), + loop(State#state{includes = NewIncludes}); + {From, stop} -> + reply(From, stopped); %% Nothing to store + {'DOWN', MRef, process, Parent, Reason} -> + exit(Reason) end. +opentab(Tab, Mod, []) -> + opentab(Tab, Mod, ["."]); +opentab(Tab, Mod, Includes) -> + Base = lists:concat([Mod, ".asn1db"]), + opentab2(Tab, Base, Mod, Includes, ok). -%%all(Tab, K) -> -%% pickup(K, ets:match(Tab, {{K, '$1'}, '$2'})). -%%pickup(K, []) -> []; -%%pickup(K, [[V1,V2] |T]) -> -%% [{{K,V1},V2} | pickup(K, T)]. +opentab2(_Tab, _Base, _Mod, [], Error) -> + Error; +opentab2(Tab, Base, Mod, [Ih|It], _Error) -> + File = filename:join(Ih, Base), + case ets:file2tab(File) of + {ok, Modtab} -> + ets:insert(Tab, {Mod, Modtab}), + {ok, Modtab}; + NewErr -> + opentab2(Tab, Base, Mod, It, NewErr) + end. lookup(Tab, K) -> case ets:lookup(Tab, K) of - [] -> undefined; - [{K,V}] -> V + [] -> undefined; + [{K,V}] -> V end. - - -dbnew(Module) -> req({new,Module}). -dbsave(OutFile,Module) -> req({save,OutFile,Module}). -dbload(Module) -> req({load,Module}). - -dbput(Module,K,V) -> req({set, Module, K, V}). -dbget(Module,K) -> req({get, Module, K}). -dbget_all(K) -> req({get_all, K}). -dbget_all_mod(Mod) -> req({all_mod,Mod}). -dbstop() -> stop_server(asn1db). -dbclear() -> req(clear). -dberase_module({module,M})-> - req({delete_mod, M}). - -req(R) -> - asn1db ! {self(), R}, - receive {asn1db, Reply} -> Reply end. - -stop_server(Name) -> - stop_server(Name, whereis(Name)). -stop_server(_, undefined) -> stopped; -stop_server(Name, _Pid) -> - Name ! {self(), stop}, - receive {Name, _} -> stopped end. - - -start_server(Name,Mod,Fun,Args) -> - case whereis(Name) of - undefined -> - register(Name, spawn(Mod,Fun, Args)); - _Pid -> - req({new_includes,Args}) - end. - - diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 39082307cb..2d17f73a2c 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1,3 +1,4 @@ +%% vim: tabstop=8:shiftwidth=4 %% %% %CopyrightBegin% %% @@ -24,12 +25,12 @@ %%-compile(export_all). %% Public exports -export([compile/1, compile/2]). --export([start/0, start/1, stop/0]). +-export([start/0, start/1]). -export([encode/2, encode/3, decode/3]). --export([test/1, test/2, test/3, value/2]). +-export([test/1, test/2, test/3, value/2, value/3]). %% Application internal exports -export([compile_asn/3,compile_asn1/3,compile_py/3,compile/3, - value/1,vsn/0, + vsn/0, get_name_of_def/1,get_pos_of_def/1]). -export([read_config_data/1,get_gen_state_field/1,get_gen_state/0, partial_inc_dec_toptype/1,save_gen_state/1,update_gen_state/2, @@ -93,29 +94,23 @@ compile(File,Options) when is_list(Options) -> end, Options1 = optimize_ber_bin(Options), Options2 = includes(File,Options1), - Includes=[I||{i,I}<-Options2], - Parent = self(), - Pid = spawn_link(fun() -> - compile_proc(File, Includes, Options2, Parent) - end), - receive {Pid, Result} -> Result end. - -compile_proc(File, Includes, Options, Parent) -> - Result = case (catch input_file_type(File, Includes)) of - {single_file, SuffixedFile} -> %% "e.g. "/tmp/File.asn" - (catch compile1(SuffixedFile, Options)); - {multiple_files_file, SetBase, FileName} -> - case get_file_list(FileName, Includes) of - FileList when is_list(FileList) -> - (catch compile_set(SetBase, FileList, Options)); - Err -> - Err - end; - Err = {input_file_error, _Reason} -> - {error, Err}; - Err2 -> Err2 - end, - Parent ! {self(), Result}. + Includes = strip_includes(Options2), + in_process(fun() -> compile_proc(File, Includes, Options2) end). + +compile_proc(File, Includes, Options) -> + case input_file_type(File, Includes) of + {single_file, SuffixedFile} -> %% "e.g. "/tmp/File.asn" + compile1(SuffixedFile, Options); + {multiple_files_file, SetBase, FileName} -> + case get_file_list(FileName, Includes) of + FileList when is_list(FileList) -> + compile_set(SetBase, FileList, Options); + Err -> + Err + end; + Err = {input_file_error, _Reason} -> + {error, Err} + end. compile1(File,Options) when is_list(Options) -> verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File],Options), @@ -126,7 +121,7 @@ compile1(File,Options) when is_list(Options) -> DbFile = outfile(Base,"asn1db",Options), Includes = [I || {i,I} <- Options], EncodingRule = get_rule(Options), - asn1ct_table:new(asn1_functab, [named_table]), + asn1ct_table:new(asn1_functab), Continue1 = scan(File,Options), Continue2 = parse(Continue1,File,Options), Continue3 = check(Continue2,File,OutFile,Includes,EncodingRule, @@ -194,7 +189,7 @@ compile_set(SetBase,Files,Options) DbFile = outfile(SetBase,"asn1db",Options), Includes = [I || {i,I} <- Options], EncodingRule = get_rule(Options), - asn1ct_table:new(asn1_functab, [named_table]), + asn1ct_table:new(asn1_functab), ScanRes = scan_set(Files,Options), ParseRes = parse_set(ScanRes,Options), Result = @@ -276,7 +271,7 @@ merge_modules(ParseRes,CommonName) -> %% causes an exit if duplicate definition names exist in a module remove_name_collisions(Modules) -> - asn1ct_table:new(renamed_defs, [named_table]), + asn1ct_table:new(renamed_defs), %% Name duplicates in the same module is not allowed. lists:foreach(fun exit_if_nameduplicate/1,Modules), %% Then remove duplicates in different modules and return the @@ -489,7 +484,7 @@ save_imports(ModuleList)-> [] -> ok; ImportsList2 -> - asn1ct_table:new(original_imports, [named_table]), + asn1ct_table:new(original_imports), lists:foreach(fun(X) -> asn1ct_table:insert(original_imports, X) end, ImportsList2) end. @@ -567,7 +562,7 @@ check_tagdefault(ModList) -> case have_same_tagdefault(ModList) of {true,TagDefault} -> TagDefault; {false,TagDefault} -> - asn1ct_table:new(automatic_tags, [named_table]), + asn1ct_table:new(automatic_tags), save_automatic_tagged_types(ModList), TagDefault end. @@ -833,22 +828,14 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) -> _ -> ok end, put(encoding_options,Options), - asn1ct_table:new(check_functions, [named_table]), + asn1ct_table:new(check_functions), %% create decoding function names and taglists for partial decode - %% For the time being leave errors unnoticed !!!!!!!!! -% io:format("Options: ~p~n",[Options]), - case catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of - {error, enoent} -> ok; - {error, Reason} -> warning("Error in configuration " - "file: ~n~p~n",[Reason],Options, - "Error in configuration file"); - {'EXIT',Reason} -> warning("Internal error when " - "analyzing configuration " - "file: ~n~p~n",[Reason],Options, - "Internal error when " - "analyzing configuration"); - _ -> ok + case specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of + {error, Reason} -> warning("Error in configuration file: ~n~p~n", + [Reason], Options, + "Error in configuration file"); + _ -> ok end, Result = @@ -1187,17 +1174,28 @@ optimize_ber_bin(Options) -> end. includes(File,Options) -> - Dir = filename:dirname(File), - Options2 = - case lists:member({i,"."},Options) of - false -> Options ++ [{i,"."}]; - _ -> Options - end, - case lists:member({i,Dir}, Options2) of - false -> Options2 ++ [{i,Dir}]; - _ -> Options2 + Options2 = include_append(".", Options), + Options3 = include_append(filename:dirname(File), Options2), + case proplists:get_value(outdir, Options) of + undefined -> Options3; + OutDir -> include_prepend(OutDir, Options3) + end. + +include_append(Dir, Options) -> + option_add({i, Dir}, Options, fun(Opts) -> Opts ++ [{i, Dir}] end). + +include_prepend(Dir, Options) -> + option_add({i, Dir}, Options, fun(Opts) -> [{i, Dir}|Opts] end). + +option_add(Option, Options, Fun) -> + case lists:member(Option, Options) of + true -> Options; + false -> Fun(Options) end. +strip_includes(Includes) -> + [I || {i, I} <- Includes]. + is_inline(Options) -> case lists:member(inline,Options) of true -> true; @@ -1227,10 +1225,7 @@ compile_py(File,OutFile,Options) -> compile(lists:concat([File,".py"]),OutFile,Options). compile(File, _OutFile, Options) -> - case catch compile(File, make_erl_options(Options)) of - Exit = {'EXIT',_Reason} -> - error("~p~n~s~n",[Exit,"error"],Options), - error; + case compile(File, make_erl_options(Options)) of {error,_Reason} -> %% case occurs due to error in asn1ct_parser2,asn1ct_check %% io:format("~p~n",[_Reason]), @@ -1243,10 +1238,7 @@ compile(File, _OutFile, Options) -> ok; ScanRes when is_list(ScanRes) -> io:format("~p~n",[ScanRes]), - ok; - Unknown -> - error("~p~n~s~n",[Unknown,"error"],Options), - error + ok end. %% Converts generic compiler options to specific options. @@ -1345,17 +1337,6 @@ start() -> start(Includes) when is_list(Includes) -> asn1_db:dbstart(Includes). -stop() -> - save(), - asn1_db:stop_server(ns), - asn1_db:stop_server(rand), - stopped. - -save() -> - asn1_db:dbstop(). - -%%clear() -> -%% asn1_db:dbclear(). encode(Module,Term) -> asn1rt:encode(Module,Term). @@ -1371,94 +1352,116 @@ decode(Module,Type,Bytes) -> asn1rt:decode(Module,Type,Bytes). -test(Module) -> - start(), - M = asn1_db:dbget(Module,'MODULE'), - {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval, - test_each(Module,Types). - -test_each(Module,[Type | Rest]) -> - case test(Module,Type) of - {ok,_Result} -> - test_each(Module,Rest); - Error -> - Error +test(Module) -> test_module(Module, []). + +test(Module, [] = Options) -> test_module(Module, Options); +test(Module, [{i, _}|_] = Options) -> test_module(Module, Options); +test(Module, Type) -> test_type(Module, Type, []). + +test(Module, Type, [] = Options) -> test_type(Module, Type, Options); +test(Module, Type, [{i, _}|_] = Options) -> test_type(Module, Type, Options); +test(Module, Type, Value) -> test_value(Module, Type, Value). + +test_module(Module, Includes) -> + in_process(fun() -> + start(strip_includes(Includes)), + case check(Module, Includes) of + {ok, NewTypes} -> test_each(Module, NewTypes); + Error -> Error + end + end). + +test_each(Module, [Type|Rest]) -> + case test_type(Module, Type) of + {ok, _Result} -> test_each(Module, Rest); + Error -> Error end; test_each(_,[]) -> ok. -test(Module,Type) -> - io:format("~p:~p~n",[Module,Type]), - case (catch value(Module,Type)) of - {ok,Val} -> - %% io:format("asn1ct:test/2: ~w~n",[Val]), - test(Module,Type,Val); - {'EXIT',Reason} -> - {error,{asn1,{value,Reason}}} +test_type(Module, Type, Includes) -> + in_process(fun() -> + start(strip_includes(Includes)), + case check(Module, Includes) of + {ok, _NewTypes} -> test_type(Module, Type); + Error -> Error + end + end). + +test_type(Module, Type) -> + case get_value(Module, Type) of + {ok, Val} -> test_value(Module, Type, Val); + {error, Reason} -> {error, {asn1, {value, Reason}}} end. +test_value(Module, Type, Value) -> + in_process(fun() -> + case catch encode(Module, Type, Value) of + {ok, Bytes} -> + M = to_atom(Module), + NewBytes = prepare_bytes(M:encoding_rule(), Bytes), + case decode(Module, Type, NewBytes) of + {ok, Value} -> + {ok, {Module, Type, Value}}; + {ok, Res} -> + {error, {asn1, + {encode_decode_mismatch, + {{Module, Type, Value}, Res}}}}; + Error -> + {error, {asn1, + {{decode, + {Module, Type, Value}, Error}}}} + end; + Error -> + {error, {asn1, + {encode, {{Module, Type, Value}, Error}}}} + end + end). + +value(Module, Type) -> value(Module, Type, []). + +value(Module, Type, Includes) -> + in_process(fun() -> + start(strip_includes(Includes)), + case check(Module, Includes) of + {ok, _NewTypes} -> get_value(Module, Type); + Error -> Error + end + end). + +get_value(Module, Type) -> + case asn1ct_value:from_type(Module, Type) of + {error, Reason} -> {error, Reason}; + Result -> {ok, Result} + end. -test(Module,Type,Value) -> - case catch encode(Module,Type,Value) of - {ok,Bytes} -> - %% io:format("test 1: ~p~n",[{Bytes}]), - M = if - is_list(Module) -> - list_to_atom(Module); - true -> - Module - end, - NewBytes = - case M:encoding_rule() of - ber -> - lists:flatten(Bytes); - ber_bin when is_binary(Bytes) -> - Bytes; - ber_bin -> - list_to_binary(Bytes); - ber_bin_v2 when is_binary(Bytes) -> - Bytes; - ber_bin_v2 -> - list_to_binary(Bytes); - per -> - lists:flatten(Bytes); - per_bin when is_binary(Bytes) -> - Bytes; - per_bin -> - list_to_binary(Bytes); - uper_bin -> - Bytes - end, - case decode(Module,Type,NewBytes) of - {ok,Value} -> - {ok,{Module,Type,Value}}; - {ok,Res} -> - {error,{asn1,{encode_decode_mismatch, - {{Module,Type,Value},Res}}}}; - Error -> - {error,{asn1,{{decode, - {Module,Type,Value},Error}}}} - end; - Error -> - {error,{asn1,{encode,{{Module,Type,Value},Error}}}} +check(Module, Includes) -> + case asn1_db:dbget(Module,'MODULE') of + undefined -> + {error, {file_not_found, lists:concat([Module, ".asn1db"])}}; + M -> + TypeOrVal = M#module.typeorval, + State = #state{mname = M#module.name, + module = M#module{typeorval=[]}, + options = Includes}, + case asn1ct_check:check(State, TypeOrVal) of + {ok, {NewTypes, _, _, _, _, _}, _} -> {ok, NewTypes}; + {error, Reason} -> {error, Reason} + end end. -value(Module) -> - start(), - M = asn1_db:dbget(Module,'MODULE'), - {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval, - lists:map(fun(A) ->value(Module,A) end,Types). +to_atom(Term) when is_list(Term) -> list_to_atom(Term); +to_atom(Term) when is_atom(Term) -> Term. -value(Module,Type) -> - start(), - case catch asn1ct_value:get_type(Module,Type,no) of - {error,Reason} -> - {error,Reason}; - {'EXIT',Reason} -> - {error,Reason}; - Result -> - {ok,Result} - end. +prepare_bytes(ber, Bytes) -> lists:flatten(Bytes); +prepare_bytes(ber_bin, Bytes) when is_binary(Bytes) -> Bytes; +prepare_bytes(ber_bin, Bytes) -> list_to_binary(Bytes); +prepare_bytes(ber_bin_v2, Bytes) when is_binary(Bytes) -> Bytes; +prepare_bytes(ber_bin_v2, Bytes) -> list_to_binary(Bytes); +prepare_bytes(per, Bytes) -> lists:flatten(Bytes); +prepare_bytes(per_bin, Bytes) when is_binary(Bytes) -> Bytes; +prepare_bytes(per_bin, Bytes) -> list_to_binary(Bytes); +prepare_bytes(uper_bin, Bytes) -> Bytes. vsn() -> ?vsn. @@ -1508,26 +1511,26 @@ partial_decode_prepare(ber_bin_v2,M,TsAndVs,Options) when is_tuple(TsAndVs) -> _ -> M#module.name end, %% io:format("ModName: ~p~nM#module.name: ~p~n~n",[ModName,M#module.name]), - CfgList = read_config_file(ModName), - SelectedDecode = get_config_info(CfgList,selective_decode), - ExclusiveDecode = get_config_info(CfgList,exclusive_decode), - CommandList = - create_partial_decode_gen_info(M#module.name,SelectedDecode), - %% To convert CommandList to a proper list for the driver change - %% the list:[[choosen,Tag1],skip,[skip_optional,Tag2]] to L = - %% [5,2,Tag1,0,1,Tag2] where 5 is the length, and call - %% port_control(asn1_driver_port,3,[L| Bin]) - save_config(partial_decode,CommandList), - save_gen_state(selective_decode,SelectedDecode), -% io:format("selective_decode: CommandList:~n~p~nSelectedDecode:~n~p~n", -% [CommandList,SelectedDecode]), - CommandList2 = - create_partial_inc_decode_gen_info(M#module.name,ExclusiveDecode), -% io:format("partial_incomplete_decode = ~p~n",[CommandList2]), - Part_inc_tlv_tags = tlv_tags(CommandList2), -% io:format("partial_incomplete_decode: tlv_tags = ~p~n",[Part_inc_tlv_tags]), - save_config(partial_incomplete_decode,Part_inc_tlv_tags), - save_gen_state(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags); + case read_config_file(ModName) of + no_config_file -> + ok; + CfgList -> + SelectedDecode = get_config_info(CfgList,selective_decode), + ExclusiveDecode = get_config_info(CfgList,exclusive_decode), + CommandList = create_partial_decode_gen_info(M#module.name, + SelectedDecode), + %% To convert CommandList to a proper list for the driver change + %% the list:[[choosen,Tag1],skip,[skip_optional,Tag2]] to L = + %% [5,2,Tag1,0,1,Tag2] where 5 is the length, and call + %% port_control(asn1_driver_port,3,[L| Bin]) + save_config(partial_decode,CommandList), + save_gen_state(selective_decode,SelectedDecode), + CommandList2 = create_partial_inc_decode_gen_info(M#module.name, + ExclusiveDecode), + Part_inc_tlv_tags = tlv_tags(CommandList2), + save_config(partial_incomplete_decode,Part_inc_tlv_tags), + save_gen_state(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags) + end; partial_decode_prepare(_,_,_,_) -> ok. @@ -2006,7 +2009,7 @@ read_config_file(ModuleName) -> read_config_file1(ModuleName,[]) -> case filename:extension(ModuleName) of ".asn1config" -> - throw({error,enoent}); + no_config_file; _ -> read_config_file(lists:concat([ModuleName,".asn1config"])) end; @@ -2035,7 +2038,7 @@ get_config_info(CfgList,InfoType) -> %% Before saving anything check if a table exists %% The record gen_state is saved with the key {asn1_config,gen_state} save_config(Key,Info) -> - asn1ct_table:new_reuse(asn1_general, [named_table]), + asn1ct_table:new_reuse(asn1_general), asn1ct_table:insert(asn1_general, {{asn1_config, Key}, Info}). read_config_data(Key) -> @@ -2569,3 +2572,21 @@ is_werr(S) when is_record(S, state) -> is_werr(S#state.options); is_werr(O) -> lists:member(warnings_as_errors, O). + + +in_process(Fun) -> + Parent = self(), + Pid = spawn_link(fun() -> process(Parent, Fun) end), + receive + {Pid, Result} -> Result; + {Pid, Class, Reason, Stack} -> + ST = try throw(x) catch throw:x -> erlang:get_stacktrace() end, + erlang:raise(Class, Reason, Stack ++ ST) + end. + +process(Parent, Fun) -> + try + Parent ! {self(), Fun()} + catch Class:Reason -> + Parent ! {self(), Class, Reason, erlang:get_stacktrace()} + end. diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 3facd3f0ee..c223561f12 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -1,3 +1,4 @@ +%% vim: tabstop=8:shiftwidth=4 %% %% %CopyrightBegin% %% @@ -94,8 +95,8 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) -> _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used %% table to save instances of parameterized objects,object sets - asn1ct_table:new(parameterized_objects, [named_table]), - asn1ct_table:new(inlined_objects, [named_table]), + asn1ct_table:new(parameterized_objects), + asn1ct_table:new(inlined_objects), Terror = checkt(S,Types,[]), @@ -4923,12 +4924,7 @@ get_referenced(S,Emod,Ename,Pos) -> %% May be an imported entity in module Emod or Emod may not exist case asn1_db:dbget(Emod,'MODULE') of undefined -> - case parse_and_save(S,Emod) of - ok -> - get_referenced(S,Emod,Ename,Pos); - _ -> - throw({error,{asn1,{module_not_found,Emod}}}) - end; + throw({error,{asn1,{module_not_found,Emod}}}); _ -> NewS = update_state(S,Emod), get_imported(NewS,Ename,Emod,Pos) @@ -4970,13 +4966,7 @@ get_imported(S,Name,Module,Pos) -> parse_and_save(S,Imodule), case asn1_db:dbget(Imodule,'MODULE') of undefined -> - case parse_and_save(S,Imodule) of - ok -> - %% check with cover - get_referenced(S,Module,Name,Pos); - _ -> - throw({error,{asn1,{module_not_found,Imodule}}}) - end; + throw({error,{asn1,{module_not_found,Imodule}}}); Im when is_record(Im,module) -> case is_exported(Im,Name) of false -> diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl index 224a535e87..007d390a1b 100644 --- a/lib/asn1/src/asn1ct_parser2.erl +++ b/lib/asn1/src/asn1ct_parser2.erl @@ -1,7 +1,8 @@ +%% vim: tabstop=8:shiftwidth=4 %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2010. All Rights Reserved. +%% Copyright Ericsson AB 2000-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -81,14 +82,15 @@ parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) -> case Rest3 of [{'::=',_L7}, {'BEGIN',_L8}|Rest4] -> {Exports, Rest5} = parse_Exports(Rest4), - {Imports, Rest6} = parse_Imports(Rest5), + {{imports, Imports}, Rest6} = parse_Imports(Rest5), + put({get(asn1_module), imports}, Imports), {#module{ pos = L1, name = ModuleIdentifier, defid = [], % fix this tagdefault = TagDefault, extensiondefault = ExtensionDefault, exports = Exports, - imports = Imports},Rest6}; + imports = {imports, Imports}}, Rest6}; _ -> throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), [got,get_token(hd(Rest3)),expected,"::= BEGIN"]}}) end; @@ -717,12 +719,12 @@ parse_DefinedType(Tokens=[{typereference,L1,TypeName}, {'EXIT',_Reason} -> Rest2 = [T2,T3|Rest], {#type{def = #'Externaltypereference'{pos=L1, - module=get(asn1_module), + module=resolve_module(TypeName), type=TypeName}},Rest2}; {asn1_error,_} -> Rest2 = [T2,T3|Rest], {#type{def = #'Externaltypereference'{pos=L1, - module=get(asn1_module), + module=resolve_module(TypeName), type=TypeName}},Rest2}; Result -> Result @@ -735,7 +737,7 @@ parse_DefinedType([{typereference,L1,Module},{'.',_},{typereference,_,TypeName}| parse_DefinedType([{typereference,L1,TypeName}|Rest]) -> case is_pre_defined_class(TypeName) of false -> - {#type{def = #'Externaltypereference'{pos=L1,module=get(asn1_module), + {#type{def = #'Externaltypereference'{pos=L1,module=resolve_module(TypeName), type=TypeName}},Rest}; _ -> throw({asn1_error, @@ -758,6 +760,21 @@ parse_SelectionType(Tokens) -> [got,get_token(hd(Tokens)),expected,'identifier <']}}). +resolve_module(Type) -> + Current = get(asn1_module), + Imports = get({Current, imports}), + resolve_module(Type, Current, Imports). + +resolve_module(_Type, Current, undefined) -> + Current; +resolve_module(Type, Current, Imports) -> + case [Mod || #'SymbolsFromModule'{symbols = S, module = Mod} <- Imports, + #'Externaltypereference'{type = T} <- S, + Type == T] of + [#'Externaltypereference'{type = Mod}] -> Mod; + [] -> Current + end. + %% -------------------------- @@ -1539,7 +1556,7 @@ parse_DefinedObjectSet([{typereference,L1,ModuleName},{'.',_}, {{objectset,L1,#'Externaltypereference'{pos=L2,module=ModuleName, type=ObjSetName}},Rest}; parse_DefinedObjectSet([{typereference,L1,ObjSetName}|Rest]) -> - {{objectset,L1,#'Externaltypereference'{pos=L1,module=get(asn1_module), + {{objectset,L1,#'Externaltypereference'{pos=L1,module=resolve_module(ObjSetName), type=ObjSetName}},Rest}; parse_DefinedObjectSet(Tokens) -> throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), @@ -3203,17 +3220,17 @@ prioritize_error(ErrList) -> tref2Exttref(#typereference{pos=Pos,val=Name}) -> #'Externaltypereference'{pos=Pos, - module=get(asn1_module), + module=resolve_module(Name), type=Name}. tref2Exttref(Pos,Name) -> #'Externaltypereference'{pos=Pos, - module=get(asn1_module), + module=resolve_module(Name), type=Name}. identifier2Extvalueref(#identifier{pos=Pos,val=Name}) -> #'Externalvaluereference'{pos=Pos, - module=get(asn1_module), + module=resolve_module(Name), value=Name}. %% lookahead_assignment/1 checks that the next sequence of tokens diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl index b7ae1d7105..a5eb6d0413 100644 --- a/lib/asn1/src/asn1ct_table.erl +++ b/lib/asn1/src/asn1ct_table.erl @@ -21,7 +21,9 @@ %% Table abstraction module for ASN.1 compiler +-export([new/1]). -export([new/2]). +-export([new_reuse/1]). -export([new_reuse/2]). -export([exists/1]). -export([size/1]). @@ -33,32 +35,42 @@ %% Always creates a new table +new(Table) -> new(Table, []). new(Table, Options) -> - case ets:info(Table) of - undefined -> - ets:new(Table, Options); - _ -> - delete(Table), - ets:new(Table, Options) - end. + TableId = case get(Table) of + undefined -> + ets:new(Table, Options); + _ -> + delete(Table), + ets:new(Table, Options) + end, + put(Table, TableId). +%% Only create it if it doesn't exist yet +new_reuse(Table) -> new_reuse(Table, []). new_reuse(Table, Options) -> not exists(Table) andalso new(Table, Options). -exists(Table) -> ets:info(Table) =/= undefined. +exists(Table) -> get(Table) =/= undefined. -size(Table) -> ets:info(Table, size). +size(Table) -> ets:info(get(Table), size). -insert(Table, Tuple) -> ets:insert(Table, Tuple). +insert(Table, Tuple) -> ets:insert(get(Table), Tuple). -lookup(Table, Key) -> ets:lookup(Table, Key). +lookup(Table, Key) -> ets:lookup(get(Table), Key). -match(Table, MatchSpec) -> ets:match(Table, MatchSpec). +match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec). -to_list(Table) -> ets:tab2list(Table). +to_list(Table) -> ets:tab2list(get(Table)). delete(Tables) when is_list(Tables) -> [delete(T) || T <- Tables], true; delete(Table) when is_atom(Table) -> - exists(Table) andalso ets:delete(Table). + case get(Table) of + undefined -> + true; + TableId -> + ets:delete(TableId), + erase(Table) + end. diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index d099376b1b..9013baef92 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -25,58 +25,58 @@ -include("asn1_records.hrl"). %-compile(export_all). --export([get_type/3]). --export([i_random/1]). - +-export([from_type/2]). %% Generate examples of values ****************************** %%****************************************x -get_type(M,Typename,Tellname) -> +from_type(M,Typename) -> case asn1_db:dbget(M,Typename) of undefined -> - {asn1_error,{not_found,{M,Typename}}}; + {error,{not_found,{M,Typename}}}; Tdef when is_record(Tdef,typedef) -> Type = Tdef#typedef.typespec, - get_type(M,[Typename],Type,Tellname); + from_type(M,[Typename],Type); + Vdef when is_record(Vdef,valuedef) -> + from_value(Vdef); Err -> - {asn1_error,{other,Err}} + {error,{other,Err}} end. -get_type(M,Typename,Type,Tellname) when is_record(Type,type) -> +from_type(M,Typename,Type) when is_record(Type,type) -> InnerType = get_inner(Type#type.def), case asn1ct_gen:type(InnerType) of #'Externaltypereference'{module=Emod,type=Etype} -> - get_type(Emod,Etype,Tellname); + from_type(Emod,Etype); {_,user} -> - case Tellname of - yes -> {Typename,get_type(M,InnerType,no)}; - no -> get_type(M,InnerType,no) - end; + from_type(M,InnerType); {notype,_} -> true; {primitive,bif} -> - get_type_prim(Type,get_encoding_rule(M)); + from_type_prim(Type,get_encoding_rule(M)); 'ASN1_OPEN_TYPE' -> case Type#type.constraint of [#'Externaltypereference'{type=TrefConstraint}] -> - get_type(M,TrefConstraint,no); + from_type(M,TrefConstraint); _ -> ERule = get_encoding_rule(M), open_type_value(ERule) end; {constructed,bif} when Typename == ['EXTERNAL'] -> - Val=get_type_constructed(M,Typename,InnerType,Type), + Val=from_type_constructed(M,Typename,InnerType,Type), asn1rt_check:transform_to_EXTERNAL1994(Val); {constructed,bif} -> - get_type_constructed(M,Typename,InnerType,Type) + from_type_constructed(M,Typename,InnerType,Type) end; -get_type(M,Typename,#'ComponentType'{name = Name,typespec = Type},_) -> - get_type(M,[Name|Typename],Type,no); -get_type(_,_,_,_) -> % 'EXTENSIONMARK' +from_type(M,Typename,#'ComponentType'{name = Name,typespec = Type}) -> + from_type(M,[Name|Typename],Type); +from_type(_,_,_) -> % 'EXTENSIONMARK' undefined. +from_value(#valuedef{type = #type{def = 'INTEGER'}, value = Val}) -> + Val. + get_inner(A) when is_atom(A) -> A; get_inner(Ext) when is_record(Ext,'Externaltypereference') -> Ext; get_inner({typereference,_Pos,Name}) -> Name; @@ -93,7 +93,7 @@ get_inner(T) when is_tuple(T) -> -get_type_constructed(M,Typename,InnerType,D) when is_record(D,type) -> +from_type_constructed(M,Typename,InnerType,D) when is_record(D,type) -> case InnerType of 'SET' -> get_sequence(M,Typename,D); @@ -132,7 +132,7 @@ get_components(M,Typename,{Root,Ext}) -> %% Should enhance this *** HERE *** with proper handling of extensions get_components(M,Typename,[H|T]) -> - [get_type(M,Typename,H,no)| + [from_type(M,Typename,H)| get_components(M,Typename,T)]; get_components(_,_,[]) -> []. @@ -145,10 +145,10 @@ get_choice(M,Typename,Type) -> {CompList,ExtList} -> % Should be enhanced to handle extensions too CList = CompList ++ ExtList, C = lists:nth(random(length(CList)),CList), - {C#'ComponentType'.name,get_type(M,Typename,C,no)}; + {C#'ComponentType'.name,from_type(M,Typename,C)}; CompList when is_list(CompList) -> C = lists:nth(random(length(CompList)),CompList), - {C#'ComponentType'.name,get_type(M,Typename,C,no)} + {C#'ComponentType'.name,from_type(M,Typename,C)} end. get_sequence_of(M,Typename,Type,TypeSuffix) -> @@ -157,14 +157,14 @@ get_sequence_of(M,Typename,Type,TypeSuffix) -> C = Type#type.constraint, S = size_random(C), NewTypeName = [TypeSuffix|Typename], - gen_list(M,NewTypeName,Oftype,no,S). + gen_list(M,NewTypeName,Oftype,S). -gen_list(_,_,_,_,0) -> +gen_list(_,_,_,0) -> []; -gen_list(M,Typename,Oftype,Tellname,N) -> - [get_type(M,Typename,Oftype,no)|gen_list(M,Typename,Oftype,Tellname,N-1)]. +gen_list(M,Typename,Oftype,N) -> + [from_type(M,Typename,Oftype)|gen_list(M,Typename,Oftype,N-1)]. -get_type_prim(D,Erule) -> +from_type_prim(D,Erule) -> C = D#type.constraint, case D#type.def of 'INTEGER' -> @@ -198,6 +198,7 @@ get_type_prim(D,Erule) -> NN = [X||{X,_} <- NNew], case NN of [] -> + io:format(user, "Enum = ~p~n", [Enum]), asn1_EMPTY; _ -> case C of @@ -412,14 +413,20 @@ adjust_list1(Len,Orig,[Oh|Ot],Acc) -> adjust_list1(Len-1,Orig,Ot,[Oh|Acc]). -get_constraint(C,Key) -> - case lists:keysearch(Key,1,C) of - false -> - no; - {value,{_,V}} -> - V +get_constraint(C, Key) -> + case lists:keyfind(Key, 1, C) of + false -> no; + {'ValueRange', {Lb, Ub}} -> {check_external(Lb), check_external(Ub)}; + {'SizeConstraint', N} -> N; + {Key, Value} -> Value end. +check_external(ExtRef) when is_record(ExtRef, 'Externalvaluereference') -> + #'Externalvaluereference'{module = Emod, value = Evalue} = ExtRef, + from_type(Emod, Evalue); +check_external(Value) -> + Value. + get_encoding_rule(M) -> Mod = if is_list(M) -> diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src index 3f51b125ec..912170fe12 100644 --- a/lib/asn1/test/asn1_SUITE.erl.src +++ b/lib/asn1/test/asn1_SUITE.erl.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1469,21 +1469,21 @@ per(Config) -> per1([M|T],DataDir,OutDir) -> ?line ok = asn1ct:compile(DataDir ++ M,[?PER,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), + ?line ok = asn1ct:test(list_to_atom(M), [{i, OutDir}]), per1(T,DataDir,OutDir); per1([],_,_) -> ok. per1_bit_opt([M|T],DataDir,OutDir) -> ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimize,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), + ?line ok = asn1ct:test(list_to_atom(M), [{i, OutDir}]), per1_bit_opt(T,DataDir,OutDir); per1_bit_opt([],_,_) -> ok. per1_opt([M|T],DataDir,OutDir) -> ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimized,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), + ?line ok = asn1ct:test(list_to_atom(M), [{i, OutDir}]), per1_opt(T,DataDir,OutDir); per1_opt([],_,_) -> ok. @@ -1546,7 +1546,7 @@ ber_other(Config) -> ber1([M|T],DataDir,OutDir) -> ?line ok = asn1ct:compile(DataDir ++ M,[?BER,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), + ?line ok = asn1ct:test(list_to_atom(M), [{i, OutDir}]), ber1(T,DataDir,OutDir); ber1([],_,_) -> ok. @@ -1948,22 +1948,22 @@ testContextSwitchingTypes(Config) -> ?line true = code:add_patha(?config(priv_dir,Config)), ?line testContextSwitchingTypes:compile(Config,?BER,[]), - ?line testContextSwitchingTypes:test(), + ?line testContextSwitchingTypes:test(Config), ?line ?ber_driver(?BER,testContextSwitchingTypes:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testContextSwitchingTypes:test()), + ?line ?ber_driver(?BER,testContextSwitchingTypes:test(Config)), ?line testContextSwitchingTypes:compile(Config,?PER,[]), - ?line testContextSwitchingTypes:test(), + ?line testContextSwitchingTypes:test(Config), ?line ?per_bit_opt(testContextSwitchingTypes:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testContextSwitchingTypes:test()), + ?line ?per_bit_opt(testContextSwitchingTypes:test(Config)), ?line ?uper_bin(testContextSwitchingTypes:compile(Config,uper_bin,[])), - ?line ?uper_bin(testContextSwitchingTypes:test()), + ?line ?uper_bin(testContextSwitchingTypes:test(Config)), ?line testContextSwitchingTypes:compile(Config,?PER,[optimize]), - ?line testContextSwitchingTypes:test(). + ?line testContextSwitchingTypes:test(Config). testTypeValueNotation(suite) -> []; testTypeValueNotation(Config) -> @@ -2181,22 +2181,22 @@ test_undecoded_rest(suite) -> []; test_undecoded_rest(Config) -> ?line ok = test_undecoded_rest:compile(Config,?BER,[]), - ?line ok = test_undecoded_rest:test([]), + ?line ok = test_undecoded_rest:test([], Config), ?line ok = test_undecoded_rest:compile(Config,?BER,[undec_rest]), - ?line ok = test_undecoded_rest:test(undec_rest), + ?line ok = test_undecoded_rest:test(undec_rest, Config), ?line ok = test_undecoded_rest:compile(Config,?PER,[]), - ?line ok = test_undecoded_rest:test([]), + ?line ok = test_undecoded_rest:test([], Config), ?line ?per_bit_opt(ok = test_undecoded_rest:compile(Config,?PER,[optimize,undec_rest])), - ?line ?per_bit_opt(ok = test_undecoded_rest:test(undec_rest)), + ?line ?per_bit_opt(ok = test_undecoded_rest:test(undec_rest, Config)), ?line ?uper_bin(ok = test_undecoded_rest:compile(Config,uper_bin,[undec_rest])), - ?line ?uper_bin(ok = test_undecoded_rest:test(undec_rest)), + ?line ?uper_bin(ok = test_undecoded_rest:test(undec_rest, Config)), ?line ok = test_undecoded_rest:compile(Config,?PER,[undec_rest]), - ?line ok = test_undecoded_rest:test(undec_rest). + ?line ok = test_undecoded_rest:test(undec_rest, Config). test_inline(suite) -> []; test_inline(Config) -> @@ -2205,7 +2205,7 @@ test_inline(Config) -> {skip,"Not runnable when cover compiled"}; _ -> ?line ok=test_inline:compile(Config,?BER,[]), - ?line test_inline:main(?BER), + ?line test_inline:main(Config, ?BER), ?line test_inline:inline1(Config,?BER,[]), ?line test_inline:performance2() end. diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl index 7d05e5c352..66c1e831c3 100644 --- a/lib/asn1/test/testContextSwitchingTypes.erl +++ b/lib/asn1/test/testContextSwitchingTypes.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ -module(testContextSwitchingTypes). -export([compile/3]). --export([test/0]). +-export([test/1]). -include_lib("test_server/include/test_server.hrl"). @@ -34,14 +34,15 @@ compile(Config,Rules,Options) -> [Rules,{outdir,OutDir}]++Options). -test() -> +test(Config) -> ?line ValT = 'ContextSwitchingTypes':'val1-T'(), ?line {ok,Bytes1} = asn1_wrapper:encode('ContextSwitchingTypes','T',ValT), ?line {ok,Result1} = asn1_wrapper:decode('ContextSwitchingTypes','T',Bytes1), ?line ok = check_EXTERNAL(Result1), - ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T'), + ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T', + [{i, ?config(priv_dir, Config)}]), ?line {ok,Bytes1_2} = asn1_wrapper:encode('ContextSwitchingTypes','T',ValT2), ?line {ok,Result1_2} = diff --git a/lib/asn1/test/testMegaco.erl b/lib/asn1/test/testMegaco.erl index ca2b1062d1..8413d00c25 100644 --- a/lib/asn1/test/testMegaco.erl +++ b/lib/asn1/test/testMegaco.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -123,9 +123,11 @@ compile(Config,Erule,Options) -> main(no_module,_) -> ok; -main('OLD-MEDIA-GATEWAY-CONTROL',_) -> +main('OLD-MEDIA-GATEWAY-CONTROL',Config) -> % Msg = msg11(), - {ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage'), + OutDir = ?config(priv_dir, Config), + {ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage', + [{i, OutDir}]), ?line {ok,Bytes} = asn1_wrapper:encode('OLD-MEDIA-GATEWAY-CONTROL', 'MegacoMessage',Msg), ?line {ok,Msg} = asn1_wrapper:decode('OLD-MEDIA-GATEWAY-CONTROL', diff --git a/lib/asn1/test/test_inline.erl b/lib/asn1/test/test_inline.erl index b7ec0d8921..8e25e65838 100644 --- a/lib/asn1/test/test_inline.erl +++ b/lib/asn1/test/test_inline.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ %% -module(test_inline). --export([compile/3,main/1,inline1/3,performance/1,performance2/0]). +-export([compile/3,main/2,inline1/3,performance/1,performance2/0]). -export([mvrasn_inlined_encdec/2,mvrasn_encdec/2, mi_encdec/2,m_encdec/2]). @@ -34,7 +34,7 @@ compile(Config,_Rules,Opt) -> ?line true = code:add_patha(DataDir), ?line ok=asn1ct:compile(DataDir++"Mvrasn.set.asn",[{inline,mvrasn_inlined},{outdir,OutDir}]++Opt), - ?line ok=asn1ct:compile(DataDir++"Mvrasn-11-6.asn",[{outdir,OutDir}]++Opt), +% ?line ok=asn1ct:compile(DataDir++"Mvrasn-11-6.asn",[{outdir,OutDir}]++Opt), ?line ok=asn1ct:compile(DataDir++"Mod.set.asn",[{inline,m},{outdir,OutDir}]++Opt), ?line ok=remove_inlined_files(OutDir,[filename:join([OutDir,X])||X<-["m.erl","m.beam"]]), @@ -71,8 +71,8 @@ inline1(Config,Rule,Opt) -> ok end. -main(_Erule) -> - ?line Val = val(), +main(Config, _Erule) -> + Val = val(Config), ?line {ok,Bytes}=asn1_wrapper:encode(mvrasn_inlined,'InsertSubscriberDataArg',Val), ?line {ok,_Val2}=asn1_wrapper:decode(mvrasn_inlined,'InsertSubscriberDataArg',Bytes). @@ -94,14 +94,15 @@ test_inline2(ber_bin_v2,Mod) -> test_inline2(_,_) -> ok. -val() -> - ?line {ok,Val} = asn1ct:value('Mvrasn-11-6','InsertSubscriberDataArg'), +val(Config) -> + {ok,Val} = asn1ct:value('Mvrasn','InsertSubscriberDataArg', + [{i, ?config(priv_dir, Config)}]), Val. performance(Config) -> ?line true = code:add_patha(?config(priv_dir,Config)), ?line true = code:add_patha(?config(data_dir,Config)), - ?line Val = val(), + Val = val(Config), %% warm up timer:tc(?MODULE,mvrasn_inlined_encdec,[2,Val]), %% performance test diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl index 4e96db070b..fb8734ac21 100644 --- a/lib/asn1/test/test_modified_x420.erl +++ b/lib/asn1/test/test_modified_x420.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -28,9 +28,9 @@ compile(Config) -> ?line DataDir = ?config(data_dir,Config), ?line OutDir = ?config(priv_dir,Config), - ok = asn1ct:compile(filename:join([DataDir,modified_x420,"PKCS7"]),[der,{outdir,OutDir}]), - ok = asn1ct:compile(filename:join([DataDir,modified_x420,"InformationFramework"]),[der,{outdir,OutDir}]), - ok = asn1ct:compile(filename:join([DataDir,modified_x420,"AuthenticationFramework"]),[der,{outdir,OutDir}]). + ok = asn1ct:compile(filename:join([DataDir,modified_x420,"PKCS7"]),[der,{outdir,OutDir},{i,OutDir}]), + ok = asn1ct:compile(filename:join([DataDir,modified_x420,"InformationFramework"]),[der,{outdir,OutDir},{i,OutDir}]), + ok = asn1ct:compile(filename:join([DataDir,modified_x420,"AuthenticationFramework"]),[der,{outdir,OutDir},{i,OutDir}]). test_io(Config) -> io:format("~p~n~n", [catch test(Config)]). diff --git a/lib/asn1/test/test_undecoded_rest.erl b/lib/asn1/test/test_undecoded_rest.erl index 647fe2bb1c..277bad3a0a 100644 --- a/lib/asn1/test/test_undecoded_rest.erl +++ b/lib/asn1/test/test_undecoded_rest.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ %% -module(test_undecoded_rest). --export([compile/3,test/1]). +-export([compile/3,test/2]). -include_lib("test_server/include/test_server.hrl"). @@ -35,8 +35,9 @@ compile(Config,Rules,Opt) -> ?line ok = asn1ct:compile(DataDir ++ "P-Record",[Rules,{outdir,OutDir}]++Opt). -test(Opt) -> - ?line {ok,Msg} = asn1ct:value('P-Record','PersonnelRecord'), +test(Opt, Config) -> + ?line {ok,Msg} = asn1ct:value('P-Record','PersonnelRecord', + [{i, ?config(priv_dir, Config)}]), ?line {ok,Bytes} = asn1_wrapper:encode('P-Record','PersonnelRecord',Msg), Bytes2 = fun(B) when is_list(B) -> |