aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1/src')
-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
6 files changed, 413 insertions, 387 deletions
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) ->