diff options
Diffstat (limited to 'lib/asn1/src/prepare_templates.erl')
-rw-r--r-- | lib/asn1/src/prepare_templates.erl | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/lib/asn1/src/prepare_templates.erl b/lib/asn1/src/prepare_templates.erl new file mode 100644 index 0000000000..83155b2e52 --- /dev/null +++ b/lib/asn1/src/prepare_templates.erl @@ -0,0 +1,135 @@ +%% +%% %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(prepare_templates). +-export([gen_asn1ct_rtt/1,gen_asn1ct_eval/1]). + +gen_asn1ct_rtt(Ms) -> + io:format("%% Generated by ~s. DO NOT EDIT THIS FILE.\n" + "%%\n" + "%% Input files:\n", [?MODULE]), + [io:put_chars(["%% ",M,$\n]) || M <- Ms], + io:nl(), + io:put_chars("-module(asn1ct_rtt).\n" + "-export([assert_defined/1,dependencies/1,code/0]).\n" + "\n"), + Forms = lists:sort(lists:append([abstract(M) || M <- Ms])), + Exp = lists:sort(exports(Forms)), + defined(Exp), + io:nl(), + Calls = calls(Forms), + R = sofs:relation(Calls), + Fam0 = sofs:relation_to_family(R), + Fam = sofs:to_external(Fam0), + dependencies(Fam), + io:nl(), + Funcs = [begin + Bin = list_to_binary([$\n|erl_pp:function(Func)]), + {{M,F,A},Bin} + end || {M,{function,_,F,A,_}=Func} <- Forms], + io:format("code() ->\n~p.\n\n", [Funcs]), + halt(0). + +gen_asn1ct_eval([File]) -> + {ok,Funcs} = file:consult(File), + asn1ct_func:start_link(), + [asn1ct_func:need(MFA) || MFA <- Funcs], + io:format("%% Generated by ~s. DO NOT EDIT THIS FILE.\n" + "%%\n" + "%% Input file: ~s\n\n", [?MODULE,File]), + io:format("-module(~s).\n", [filename:rootname(File)]), + gen_asn1ct_eval_exp(Funcs), + asn1ct_func:generate(group_leader()), + halt(0). + +gen_asn1ct_eval_exp(Funcs) -> + io:put_chars("-export(["), + gen_asn1ct_eval_exp_1(Funcs, ""), + io:put_chars("]).\n"). + +gen_asn1ct_eval_exp_1([{_,F,A}|T], Sep) -> + io:put_chars(Sep), + io:format("~p/~p", [F,A]), + gen_asn1ct_eval_exp_1(T, ",\n"); +gen_asn1ct_eval_exp_1([], _) -> ok. + +defined([H|T]) -> + io:format("assert_defined(~p) -> ok", [H]), + case T of + [] -> + io:put_chars(".\n"); + [_|_] -> + io:put_chars(";\n"), + defined(T) + end. + +dependencies([{K,V}|T]) -> + io:format("dependencies(~p) ->\n~p;\n", [K,V]), + dependencies(T); +dependencies([]) -> + io:put_chars("dependencies(_) -> [].\n"). + +abstract(File) -> + {ok,{M0,[{abstract_code,Abstract}]}} = + beam_lib:chunks(File, [abstract_code]), + {raw_abstract_v1,Forms} = Abstract, + M = module(M0), + [{M,F} || F <- Forms]. + +module(M0) -> + "asn1rtt_" ++ M = atom_to_list(M0), + list_to_atom(M). + +exports([{M,{attribute,_,export,L}}|T]) -> + [{M,F,A} || {F,A} <- L] ++ exports(T); +exports([_|T]) -> + exports(T); +exports([]) -> []. + +calls([{M,{function,_,F,A,Body}}|T]) -> + MFA = {M,F,A}, + case find_calls(Body, M) -- [MFA] of + [] -> + calls(T); + [_|_]=Calls -> + [{MFA,Callee} || Callee <- Calls] ++ calls(T) + end; +calls([_|T]) -> + calls(T); +calls([]) -> []. + +find_calls([{call,_,{atom,_,F},Args}|T], M) -> + Calls = find_calls(Args, M) ++ find_calls(T, M), + Arity = length(Args), + case is_bif(F, Arity) of + false -> + [{M,F,Arity}|Calls]; + true -> + Calls + end; +find_calls([{'fun',_,{function,F,A}}|T], M) -> + [{M,F,A}|find_calls(T, M)]; +find_calls([H|T], M) -> + find_calls(H, M) ++ find_calls(T, M); +find_calls(Tuple, M) when is_tuple(Tuple) -> + find_calls(tuple_to_list(Tuple), M); +find_calls(_, _) -> []. + +is_bif(F, Arity) -> + erl_internal:bif(F, Arity). |