aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/src/prepare_templates.erl
blob: 724216698955a806cc8eeea3aa7d5912a743ada0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
%%
%% %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_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).

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).