aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1/src')
-rw-r--r--lib/asn1/src/Makefile5
-rw-r--r--lib/asn1/src/asn1_db.erl257
-rw-r--r--lib/asn1/src/asn1ct.erl433
-rw-r--r--lib/asn1/src/asn1ct_check.erl62
-rw-r--r--lib/asn1/src/asn1ct_gen.erl11
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl4
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl4
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl4
-rw-r--r--lib/asn1/src/asn1ct_name.erl89
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl37
-rw-r--r--lib/asn1/src/asn1ct_table.erl76
-rw-r--r--lib/asn1/src/asn1ct_value.erl79
12 files changed, 562 insertions, 499 deletions
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 3a59773d93..5614cbea91 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -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
@@ -58,7 +58,8 @@ CT_MODULES= \
asn1ct_gen_ber_bin_v2 \
asn1ct_value \
asn1ct_tok \
- asn1ct_parser2
+ asn1ct_parser2 \
+ asn1ct_table
RT_MODULES= \
asn1rt \
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 85bb5b2f28..2d17f73a2c 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -1,7 +1,8 @@
+%% vim: tabstop=8:shiftwidth=4
%%
%% %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
@@ -24,13 +25,13 @@
%%-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,
- create_ets_table/2,get_name_of_def/1,get_pos_of_def/1]).
+ 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,
get_tobe_refed_func/1,reset_gen_state/0,is_function_generated/1,
@@ -93,25 +94,24 @@ compile(File,Options) when is_list(Options) ->
end,
Options1 = optimize_ber_bin(Options),
Options2 = includes(File,Options1),
- Includes=[I||{i,I}<-Options2],
- case (catch input_file_type(File,Includes)) of
- {single_file,SuffixedFile} -> %% "e.g. "/tmp/File.asn"
- (catch compile1(SuffixedFile,Options2));
- {multiple_files_file,SetBase,FileName} ->
- FileList = get_file_list(FileName,Includes),
-%% io:format("FileList: ~p~n",[FileList]),
- case FileList of
- L when is_list(L) ->
- (catch compile_set(SetBase,FileList,Options2));
- Err ->
- Err
- end;
- Err = {input_file_error,_Reason} ->
- {error,Err};
- Err2 -> Err2
+ 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),
verbose("Compiler Options: ~p~n",[Options],Options),
@@ -121,13 +121,13 @@ compile1(File,Options) when is_list(Options) ->
DbFile = outfile(Base,"asn1db",Options),
Includes = [I || {i,I} <- Options],
EncodingRule = get_rule(Options),
- create_ets_table(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,
DbFile,Options,[]),
Continue4 = generate(Continue3,OutFile,EncodingRule,Options),
- delete_tables([asn1_functab]),
+ asn1ct_table:delete(asn1_functab),
Ret = compile_erl(Continue4,OutFile,Options),
case inline(is_inline(Options),
inline_output(Options,filename:rootname(File)),
@@ -189,7 +189,7 @@ compile_set(SetBase,Files,Options)
DbFile = outfile(SetBase,"asn1db",Options),
Includes = [I || {i,I} <- Options],
EncodingRule = get_rule(Options),
- create_ets_table(asn1_functab,[named_table]),
+ asn1ct_table:new(asn1_functab),
ScanRes = scan_set(Files,Options),
ParseRes = parse_set(ScanRes,Options),
Result =
@@ -214,7 +214,7 @@ compile_set(SetBase,Files,Options)
{error,{'unexpected error in scan/parse phase',
lists:map(fun(X)->element(3,X) end,Other)}}
end,
- delete_tables([asn1_functab]),
+ asn1ct_table:delete(asn1_functab),
Result.
check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
@@ -226,7 +226,7 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
Options,InputModules),
Continue2 = generate(Continue1,OutFile,EncRule,Options),
- delete_tables([renamed_defs,original_imports,automatic_tags]),
+ asn1ct_table:delete([renamed_defs, original_imports, automatic_tags]),
Ret = compile_erl(Continue2,OutFile,Options),
case inline(is_inline(Options),
@@ -247,12 +247,11 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
merge_modules(ParseRes,CommonName) ->
ModuleList = lists:map(fun(X)->element(2,X) end,ParseRes),
NewModuleList = remove_name_collisions(ModuleList),
- case ets:info(renamed_defs,size) of
- 0 -> ets:delete(renamed_defs);
- _ -> ok
+ case asn1ct_table:size(renamed_defs) of
+ 0 -> asn1ct_table:delete(renamed_defs);
+ _ -> ok
end,
save_imports(NewModuleList),
-% io:format("~p~n~p~n~p~n~n",[ets:lookup(original_imports,'M1'),ets:lookup(original_imports,'M2'),ets:tab2list(original_imports)]),
TypeOrVal = lists:append(lists:map(fun(X)->X#module.typeorval end,
NewModuleList)),
InputMNameList = lists:map(fun(X)->X#module.name end,
@@ -272,7 +271,7 @@ merge_modules(ParseRes,CommonName) ->
%% causes an exit if duplicate definition names exist in a module
remove_name_collisions(Modules) ->
- create_ets_table(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
@@ -304,7 +303,8 @@ remove_name_collisions2(ModName,[T|Ts],Ms,Acc) ->
%% rename T
NewT = set_name_of_def(ModName,Name,T), %rename def
warn_renamed_def(ModName,get_name_of_def(NewT),Name),
- ets:insert(renamed_defs,{get_name_of_def(NewT),Name,ModName}),
+ asn1ct_table:insert(renamed_defs,
+ {get_name_of_def(NewT), Name, ModName}),
remove_name_collisions2(ModName,Ts,NewMs,[NewT|Acc]);
{NewMs,?dupl_equaldefs} -> % name duplicates, but identical defs
%% keep name of T
@@ -328,8 +328,8 @@ discover_dupl_in_mods(Name,Def,[M=#module{name=N,typeorval=TorV}|Ms],
%% rename def
NewT=set_name_of_def(N,Name,T),
warn_renamed_def(N,get_name_of_def(NewT),Name),
- ets:insert(renamed_defs,{get_name_of_def(NewT),
- Name,N}),
+ asn1ct_table:insert(renamed_defs,
+ {get_name_of_def(NewT), Name, N}),
{NewT,?dupl_uniquedefs bor RenamedOrDupl};
{Name,equal} ->
%% delete def
@@ -484,8 +484,9 @@ save_imports(ModuleList)->
[] ->
ok;
ImportsList2 ->
- create_ets_table(original_imports,[named_table]),
- lists:foreach(fun(X) -> ets:insert(original_imports,X) end,ImportsList2)
+ asn1ct_table:new(original_imports),
+ lists:foreach(fun(X) -> asn1ct_table:insert(original_imports, X) end,
+ ImportsList2)
end.
@@ -561,7 +562,7 @@ check_tagdefault(ModList) ->
case have_same_tagdefault(ModList) of
{true,TagDefault} -> TagDefault;
{false,TagDefault} ->
- create_ets_table(automatic_tags,[named_table]),
+ asn1ct_table:new(automatic_tags),
save_automatic_tagged_types(ModList),
TagDefault
end.
@@ -588,7 +589,7 @@ save_automatic_tagged_types([#module{tagdefault='AUTOMATIC',
typeorval=TorV}|Ms]) ->
Fun =
fun(T) ->
- ets:insert(automatic_tags,{get_name_of_def(T)})
+ asn1ct_table:insert(automatic_tags, {get_name_of_def(T)})
end,
lists:foreach(Fun,TorV),
save_automatic_tagged_types(Ms);
@@ -827,22 +828,14 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
_ -> ok
end,
put(encoding_options,Options),
- create_ets_table(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 =
@@ -859,7 +852,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
erase(encoding_options),
erase(tlv_format), % used in ber_bin, optimize
erase(class_default_type),% used in ber_bin, optimize
- ets:delete(check_functions),
+ asn1ct_table:delete(check_functions),
case Result of
{error,_} ->
{false,Result};
@@ -1181,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;
@@ -1221,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]),
@@ -1237,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.
@@ -1339,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).
@@ -1365,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.
@@ -1484,38 +1493,6 @@ print_listing([],_) ->
ok.
-%% functions to administer ets tables
-
-%% Always creates a new table
-create_ets_table(Name,Options) when is_atom(Name) ->
- case ets:info(Name) of
- undefined ->
- ets:new(Name,Options);
- _ ->
- ets:delete(Name),
- ets:new(Name,Options)
- end.
-
-%% Creates a new ets table only if no table exists
-create_if_no_table(Name,Options) ->
- case ets:info(Name) of
- undefined ->
- %% create a new table
- create_ets_table(Name,Options);
- _ -> ok
- end.
-
-
-delete_tables([Table|Ts]) ->
- case ets:info(Table) of
- undefined -> ok;
- _ -> ets:delete(Table)
- end,
- delete_tables(Ts);
-delete_tables([]) ->
- ok.
-
-
specialized_decode_prepare(Erule,M,TsAndVs,Options) ->
case lists:member(asn1config,Options) of
true ->
@@ -1534,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.
@@ -2032,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;
@@ -2061,14 +2038,14 @@ 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) ->
- create_if_no_table(asn1_general,[named_table]),
- ets:insert(asn1_general,{{asn1_config,Key},Info}).
+ asn1ct_table:new_reuse(asn1_general),
+ asn1ct_table:insert(asn1_general, {{asn1_config, Key}, Info}).
read_config_data(Key) ->
- case ets:info(asn1_general) of
- undefined -> undefined;
- _ ->
- case ets:lookup(asn1_general,{asn1_config,Key}) of
+ case asn1ct_table:exists(asn1_general) of
+ false -> undefined;
+ true ->
+ case asn1ct_table:lookup(asn1_general,{asn1_config,Key}) of
[{_,Data}] -> Data;
Err -> % Err is [] when nothing was saved in the ets table
%% io:format("strange data from config file ~w~n",[Err]),
@@ -2595,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 e318477234..c223561f12 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -1,7 +1,8 @@
+%% vim: tabstop=8:shiftwidth=4
%%
%% %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
@@ -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:create_ets_table(parameterized_objects,[named_table]),
- asn1ct:create_ets_table(inlined_objects,[named_table]),
+ asn1ct_table:new(parameterized_objects),
+ asn1ct_table:new(inlined_objects),
Terror = checkt(S,Types,[]),
@@ -144,17 +145,17 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
NewObjectSets,
[],[],[]),
?dbg("checko finished with errors:~n~p~n~n",[Oerror]),
- InlinedObjTuples = ets:tab2list(inlined_objects),
+ InlinedObjTuples = asn1ct_table:to_list(inlined_objects),
InlinedObjects = lists:map(Element2,InlinedObjTuples),
- ets:delete(inlined_objects),
- ParameterizedElems = ets:tab2list(parameterized_objects),
+ asn1ct_table:delete(inlined_objects),
+ ParameterizedElems = asn1ct_table:to_list(parameterized_objects),
ParObjectSets = lists:filter(fun({_OSName,objectset,_}) -> true;
(_)-> false end,ParameterizedElems),
ParObjectSetNames = lists:map(Element1,ParObjectSets),
ParTypes = lists:filter(fun({_TypeName,type,_}) -> true;
(_) -> false end, ParameterizedElems),
ParTypesNames = lists:map(Element1,ParTypes),
- ets:delete(parameterized_objects),
+ asn1ct_table:delete(parameterized_objects),
put(asn1_reference,undefined),
Exporterror = check_exports(S,S#state.module),
@@ -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 ->
@@ -5116,16 +5106,16 @@ renamed_reference(S,#'Externaltypereference'{type=Name,module=Module}) ->
renamed_reference(S,Name,Module) ->
%% first check if there is a renamed type in this module
%% second check if any type was imported with this name
- case ets:info(renamed_defs) of
- undefined -> undefined;
- _ ->
- case ets:match(renamed_defs,{'$1',Name,Module}) of
+ case asn1ct_table:exists(renamed_defs) of
+ false -> undefined;
+ true ->
+ case asn1ct_table:match(renamed_defs, {'$1',Name,Module}) of
[] ->
- case ets:info(original_imports) of
- undefined ->
+ case asn1ct_table:exists(original_imports) of
+ false ->
undefined;
- _ ->
- case ets:match(original_imports,{Module,'$1'}) of
+ true ->
+ case asn1ct_table:match(original_imports, {Module,'$1'}) of
[] ->
undefined;
[[ImportsList]] ->
@@ -5253,6 +5243,9 @@ check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when is_integer(Num) ->
check_int(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
Val = dbget_ex(S,S#state.mname,Name),
check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
+check_int(S,[{'NamedNumber',Id,{'Externalvaluereference',_,Mod,Name}}|T],Acc) ->
+ Val = dbget_ex(S,Mod,Name),
+ check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
check_int(_S,[],Acc) ->
lists:keysort(2,Acc).
@@ -6002,17 +5995,12 @@ tag_nums_root2([],Ext,Root2) ->
[0,Ext,Root2].
is_automatic_tagged_in_multi_file(Name) ->
- case ets:info(automatic_tags) of
- undefined ->
+ case asn1ct_table:exists(automatic_tags) of
+ false ->
%% this case when not multifile compilation
false;
- _ ->
-% case ets:member(automatic_tags,Name) of
- case ets:lookup(automatic_tags,Name) of
-% true ->
-% true;
-% _ ->
-% false
+ true ->
+ case asn1ct_table:lookup(automatic_tags, Name) of
[] -> false;
_ -> true
end
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 0f8833f716..fda4e1c6d9 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.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
@@ -169,7 +169,7 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) ->
pgen_objectsets(Rtmod,Erules,Module,T).
pgen_check_defaultval(Erules,Module) ->
- CheckObjects = ets:tab2list(check_functions),
+ CheckObjects = asn1ct_table:to_list(check_functions),
case get(asndebug) of
true ->
FileName = lists:concat([Module,".table"]),
@@ -1598,7 +1598,7 @@ gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->
NameList = [Cname|TopType],
Name = list2name(NameList ++ [check]),
emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
- ets:insert(check_functions,{Name,Type}),
+ asn1ct_table:insert(check_functions, {Name, Type}),
%% Must look for check functions in InnerType,
%% that may be referenced or internal defined
%% constructed types not used elsewhere.
@@ -1744,10 +1744,9 @@ lookahead_reference(#'Externaltypereference'{module=M,type=T}) ->
end.
insert_once(Table,Object) ->
- _Info = ets:info(Table),
- case ets:lookup(Table,element(1,Object)) of
+ case asn1ct_table:lookup(Table, element(1, Object)) of
[] ->
- ets:insert(Table,Object); %returns true
+ asn1ct_table:insert(Table, Object); %returns true
_ -> false
end.
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 365bb84d52..597fb0030b 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-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
@@ -1834,7 +1834,7 @@ mk_object_val(Val, Ack, Len) ->
mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
add_func(F={_Func,_Arity}) ->
- ets:insert(asn1_functab,{F}).
+ asn1ct_table:insert(asn1_functab, {F}).
%% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding
%% and therefore we only filter away the ExtensionAdditionGroup start and end markers
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index b90a0adf81..8fd7a69a19 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -358,6 +358,10 @@ greatest_common_range2({_,Int},VR={_Lb,_Ub}) when is_integer(Int) ->
greatest_common_range2({_,L},{Lb,Ub}) when is_list(L) ->
Min = least_Lb([Lb|L]),
Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range2({Lb1,Ub1},{Lb2,Ub2}) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
[{'ValueRange',{Min,Max}}].
mk_vr([{Type,I}]) when is_atom(Type), is_integer(I) ->
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 1a0a0e211d..fb9613c18d 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -704,6 +704,10 @@ greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when is_integer(Int) ->
greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when is_list(L) ->
Min = least_Lb([Lb|L]),
Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range([{_,{Lb1,Ub1}}],[{_,{Lb2,Ub2}}]) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
[{'ValueRange',{Min,Max}}].
diff --git a/lib/asn1/src/asn1ct_name.erl b/lib/asn1/src/asn1ct_name.erl
index a6aa4255cc..3ab6f7b0ed 100644
--- a/lib/asn1/src/asn1ct_name.erl
+++ b/lib/asn1/src/asn1ct_name.erl
@@ -1,7 +1,7 @@
%%
%% %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
@@ -20,8 +20,7 @@
-module(asn1ct_name).
%%-compile(export_all).
--export([name_server_loop/1,
- start/0,
+-export([start/0,
stop/0,
push/1,
pop/1,
@@ -35,38 +34,50 @@
new/1]).
start() ->
- start_server(asn1_ns, asn1ct_name,name_server_loop,[[]]).
+ Parent = self(),
+ case get(?MODULE) of
+ undefined ->
+ put(?MODULE, spawn_link(fun() ->
+ Ref = monitor(process, Parent),
+ name_server_loop({Ref,Parent},[])
+ end)),
+ ok;
+ _Pid ->
+ already_started
+ end.
-stop() -> stop_server(asn1_ns).
+stop() ->
+ req(stop),
+ erase(?MODULE).
-name_server_loop(Vars) ->
+name_server_loop({Ref, Parent} = Monitor,Vars) ->
%% io:format("name -- ~w~n",[Vars]),
receive
{From,{current,Variable}} ->
- From ! {asn1_ns,get_curr(Vars,Variable)},
- name_server_loop(Vars);
+ From ! {?MODULE,get_curr(Vars,Variable)},
+ name_server_loop(Monitor,Vars);
{From,{pop,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(pop_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,pop_var(Vars,Variable));
{From,{push,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(push_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,push_var(Vars,Variable));
{From,{delete,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(delete_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,delete_var(Vars,Variable));
{From,{new,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(new_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,new_var(Vars,Variable));
{From,{prev,Variable}} ->
- From ! {asn1_ns,get_prev(Vars,Variable)},
- name_server_loop(Vars);
+ From ! {?MODULE,get_prev(Vars,Variable)},
+ name_server_loop(Monitor,Vars);
{From,{next,Variable}} ->
- From ! {asn1_ns,get_next(Vars,Variable)},
- name_server_loop(Vars);
+ From ! {?MODULE,get_next(Vars,Variable)},
+ name_server_loop(Monitor,Vars);
+ {'DOWN', Ref, process, Parent, Reason} ->
+ exit(Reason);
{From,stop} ->
- unregister(asn1_ns),
- From ! {asn1_ns,stopped},
- exit(normal)
+ From ! {?MODULE,stopped}
end.
active(V) ->
@@ -76,12 +87,16 @@ active(V) ->
end.
req(Req) ->
- asn1_ns ! {self(), Req},
- receive {asn1_ns, Reply} -> Reply end.
+ get(?MODULE) ! {self(), Req},
+ receive
+ {?MODULE, Reply} -> Reply
+ after 5000 ->
+ exit(name_server_timeout)
+ end.
pop(V) -> req({pop,V}).
push(V) -> req({push,V}).
-clear() -> req(stop), start().
+clear() -> stop(), start().
curr(V) -> req({current,V}).
new(V) -> req({new,V}).
delete(V) -> req({delete,V}).
@@ -209,25 +224,3 @@ get_next(Vars,Variable) ->
_ ->
none
end.
-
-
-stop_server(Name) ->
- stop_server(Name, whereis(Name)).
-stop_server(_Name, undefined) -> stopped;
-stop_server(Name, _Pid) ->
- Name ! {self(), stop},
- receive {Name, _} -> stopped end.
-
-
-start_server(Name,Mod,Fun,Args) ->
- case whereis(Name) of
- undefined ->
- case catch register(Name, spawn(Mod,Fun, Args)) of
- {'EXIT',{badarg,_}} ->
- start_server(Name,Mod,Fun,Args);
- _ ->
- ok
- end;
- _Pid ->
- already_started
- end.
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
new file mode 100644
index 0000000000..a5eb6d0413
--- /dev/null
+++ b/lib/asn1/src/asn1ct_table.erl
@@ -0,0 +1,76 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(asn1ct_table).
+
+%% 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]).
+-export([insert/2]).
+-export([lookup/2]).
+-export([match/2]).
+-export([to_list/1]).
+-export([delete/1]). % TODO: Remove (since we run in a separate process)
+
+
+%% Always creates a new table
+new(Table) -> new(Table, []).
+new(Table, Options) ->
+ 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) -> get(Table) =/= undefined.
+
+size(Table) -> ets:info(get(Table), size).
+
+insert(Table, Tuple) -> ets:insert(get(Table), Tuple).
+
+lookup(Table, Key) -> ets:lookup(get(Table), Key).
+
+match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec).
+
+to_list(Table) -> ets:tab2list(get(Table)).
+
+delete(Tables) when is_list(Tables) ->
+ [delete(T) || T <- Tables],
+ true;
+delete(Table) when is_atom(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) ->