aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Lindberg <[email protected]>2012-01-12 15:42:21 +0100
committerAdam Lindberg <[email protected]>2012-02-28 14:59:32 +0100
commitaa4e27ebac9eb287069fab859fe5dcdab82c75bf (patch)
tree7303d7d5f04c888a7934b783937ac2e3dc7f978a
parent93f0641c2122d6c23e2ac5f18579ef879599fc16 (diff)
downloadotp-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.xml94
-rw-r--r--lib/asn1/src/asn1_db.erl257
-rw-r--r--lib/asn1/src/asn1ct.erl367
-rw-r--r--lib/asn1/src/asn1ct_check.erl20
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl37
-rw-r--r--lib/asn1/src/asn1ct_table.erl40
-rw-r--r--lib/asn1/src/asn1ct_value.erl79
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src36
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl9
-rw-r--r--lib/asn1/test/testMegaco.erl8
-rw-r--r--lib/asn1/test/test_inline.erl17
-rw-r--r--lib/asn1/test/test_modified_x420.erl8
-rw-r--r--lib/asn1/test/test_undecoded_rest.erl9
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) ->