%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2012-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% -module(prepare_templates). -export([gen_asn1ct_rtt/1,gen_asn1ct_eval/1]). gen_asn1ct_rtt(Ms) -> {ok,Fd} = file:open("asn1ct_rtt.erl", [write]), io:format(Fd, "%% Generated by ~s. DO NOT EDIT THIS FILE.\n" "%%\n" "%% Input files:\n", [?MODULE]), [io:put_chars(Fd, ["%% ",M,$\n]) || M <- Ms], io:nl(Fd), io:put_chars(Fd, "-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(Fd, Exp), io:nl(Fd), Calls = calls(Forms), R = sofs:relation(Calls), Fam0 = sofs:relation_to_family(R), Fam = sofs:to_external(Fam0), dependencies(Fd, Fam), io:nl(Fd), Funcs = [begin Bin = list_to_binary([$\n|erl_pp:function(Func)]), {{M,F,A},Bin} end || {M,{function,_,F,A,_}=Func} <- Forms], io:format(Fd, "code() ->\n~p.\n\n", [Funcs]), ok = file:close(Fd), halt(0). gen_asn1ct_eval([File]) -> Output = filename:rootname(File, ".funcs") ++ ".erl", {ok,Fd} = file:open(Output, [write]), {ok,Funcs} = file:consult(File), asn1ct_func:start_link(), [asn1ct_func:need(MFA) || MFA <- Funcs], io:format(Fd, "%% Generated by ~s. DO NOT EDIT THIS FILE.\n" "%%\n" "%% Input file: ~s\n\n", [?MODULE,File]), io:format(Fd, "-module(~s).\n", [filename:rootname(File)]), gen_asn1ct_eval_exp(Fd, Funcs), asn1ct_func:generate(Fd), ok = file:close(Fd), halt(0). gen_asn1ct_eval_exp(Fd, Funcs) -> io:put_chars(Fd, "-export(["), gen_asn1ct_eval_exp_1(Fd, Funcs, ""), io:put_chars(Fd, "]).\n"). gen_asn1ct_eval_exp_1(Fd, [{_,F,A}|T], Sep) -> io:put_chars(Fd, Sep), io:format(Fd, "~p/~p", [F,A]), gen_asn1ct_eval_exp_1(Fd, T, ",\n"); gen_asn1ct_eval_exp_1(_, [], _) -> ok. defined(Fd, [H|T]) -> io:format(Fd, "assert_defined(~p) -> ok", [H]), case T of [] -> io:put_chars(Fd, ".\n"); [_|_] -> io:put_chars(Fd, ";\n"), defined(Fd, T) end. dependencies(Fd, [{K,V}|T]) -> io:format(Fd, "dependencies(~p) ->\n~p;\n", [K,V]), dependencies(Fd, T); dependencies(Fd, []) -> io:put_chars(Fd, "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).