1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
18
-module(snmp_mib_to_hrl).
20
-include("snmp_types.hrl").
21
-include("snmp_generic.hrl").
22
-include_lib("stdlib/include/erl_compile.hrl").
25
-export([convert/1, compile/3]).
27
%%-----------------------------------------------------------------
29
%% Args: MibName = string() without extension.
30
%% Purpose: Produce a .hrl file with oid for tables and variables,
31
%% column numbers for columns and values for enums.
32
%% Writes only the first occurence of a name. Prints a
33
%% warning if a duplicate name is found.
34
%% Returns: ok | {error, Reason}
35
%% Note: The Mib must be compiled.
36
%%-----------------------------------------------------------------
38
MibFile = MibName ++ ".bin",
39
HrlFile = MibName ++ ".hrl",
40
convert(MibFile, HrlFile, MibName, true).
42
convert(MibFile, HrlFile, MibName, Verbose) ->
43
case snmp_misc:read_mib(MibFile) of
44
{ok, #mib{asn1_types = Types, mes = MEs, traps = Traps}} ->
45
resolve(Types, MEs, Traps, HrlFile,
46
filename:basename(MibName), Verbose),
52
resolve(Types, MEs, Traps, HrlFile, MibName, Verbose) ->
53
case file:open(HrlFile, write) of
56
insert_begin(Fd, MibName),
57
insert_notifs(Traps, Fd),
59
insert_range(MEs, Fd),
60
insert_enums(Types, MEs, Fd),
61
insert_defvals(MEs, Fd),
66
io:format("~p written.~n", [HrlFile]);
75
io:format(Fd, "%%% This file was automatically generated by "
76
"snmp_mib_to_hrl v~s~n", [?version]),
79
io:format(Fd, "%%% Date: ~2.2.0w-~s-~w::~2.2.0w:~2.2.0w:~2.2.0w~n",
80
[D,month(Mo),Y,H,Mi,S]).
82
insert_begin(Fd, MibName) ->
85
"-define('~s', true).~n", [MibName, MibName]).
88
io:format(Fd, "-endif.~n", []).
90
insert_oids([#me{imported = true} | T], Fd) ->
92
insert_oids([#me{entrytype = table_column, oid = Oid, aliasname = Name} | T],
94
io:format(Fd, "-define(~w, ~w).~n", [Name, lists:last(Oid)]),
96
insert_oids([#me{entrytype = variable, oid = Oid, aliasname = Name} | T],
98
io:format(Fd, "-define(~w, ~w).~n", [Name, Oid]),
99
io:format(Fd, "-define(~w, ~w).~n", [merge_atoms(Name, instance),
102
insert_oids([#me{oid = Oid, aliasname = Name} | T], Fd) ->
103
io:format(Fd, "~n-define(~w, ~w).~n", [Name, Oid]),
105
insert_oids([], _Fd) -> ok.
108
insert_notifs(Traps, Fd) ->
109
Notifs = [Notif || #notification{} = Notif <- Traps],
114
io:format(Fd, "~n%% Notifications~n", []),
115
insert_notifs2(Notifs, Fd)
118
insert_notifs2([], _Fd) ->
120
insert_notifs2([#notification{trapname = Name, oid = Oid}|T], Fd) ->
121
io:format(Fd, "-define(~w, ~w).~n", [Name, Oid]),
122
insert_notifs2(T, Fd);
123
insert_notifs2([_|T], Fd) -> % Crap
124
insert_notifs2(T, Fd).
126
%%-----------------------------------------------------------------
127
%% There's nothing strange with this function! Enums can be
128
%% defined in types and in mibentries; therefore, we first call
129
%% ins_types and then ins_mes to insert enums from different places.
130
%%-----------------------------------------------------------------
131
insert_enums(Types, MEs, Fd) ->
132
T = ins_types(Types, Fd, []),
135
%% Insert all types, but not the imported. Ret the names of inserted
137
ins_types([#asn1_type{aliasname = Name,
139
imported = false} | T],
142
case lists:keysearch(enums, 1, Alist) of
143
{value, {enums, Enums}} when Enums /= [] ->
145
[] -> ins_types(T, Fd, Res);
147
io:format(Fd, "~n%% Definitions from ~w~n", [Name]),
148
ins_enums(NewEnums, Name, Fd),
149
ins_types(T, Fd, [Name | Res])
151
_ -> ins_types(T, Fd, Res)
153
ins_types([_ | T], Fd, Res) ->
154
ins_types(T, Fd, Res);
155
ins_types([], _Fd, Res) -> Res.
157
ins_mes([#me{entrytype = internal} | T], Types, Fd) ->
158
ins_mes(T, Types, Fd);
159
ins_mes([#me{entrytype = table} | T], Types, Fd) ->
160
ins_mes(T, Types, Fd);
161
ins_mes([#me{aliasname = Name,
162
asn1_type = #asn1_type{assocList = Alist,
164
imported = false} | T],
167
case lists:keysearch(enums, 1, Alist) of
168
{value, {enums, Enums}} when Enums /= [] ->
170
[] -> ins_mes(T, Types, Fd);
172
%% Now, check if the type is already inserted
174
case lists:member(Aname, Types) of
176
io:format(Fd, "~n%% Enum definitions from ~w~n",
178
ins_enums(NewEnums, Name, Fd),
179
ins_mes(T, Types, Fd);
180
_ -> ins_mes(T, Types, Fd)
183
_ -> ins_mes(T, Types, Fd)
185
ins_mes([_ | T], Types, Fd) ->
186
ins_mes(T, Types, Fd);
187
ins_mes([], _Types, _Fd) -> ok.
189
ins_enums([{Name, Val} | T], Origin, Fd) ->
190
EnumName = merge_atoms(Origin, Name),
191
io:format(Fd, "-define(~w, ~w).~n", [EnumName, Val]),
192
ins_enums(T, Origin, Fd);
193
ins_enums([], _Origin, _Fd) ->
196
%%----------------------------------------------------------------------
197
%% Solves the problem with placing '' around some atoms.
198
%% You can't write two atoms using ~w_~w.
199
%%----------------------------------------------------------------------
200
merge_atoms(TypeOrigin, Name) ->
201
list_to_atom(lists:append([atom_to_list(TypeOrigin), "_",
202
atom_to_list(Name)])).
204
insert_defvals(Mes, Fd) ->
205
io:format(Fd, "~n%% Default values~n", []),
206
insert_defvals2(Mes, Fd),
207
io:format(Fd, "~n", []).
209
insert_defvals2([#me{imported = true} | T], Fd) ->
210
insert_defvals2(T, Fd);
211
insert_defvals2([#me{entrytype = table_column, assocList = Alist,
212
aliasname = Name} | T],
214
case snmp_misc:assq(defval, Alist) of
216
Atom = merge_atoms('default', Name),
217
io:format(Fd, "-define(~w, ~w).~n", [Atom, Val]);
220
insert_defvals2(T, Fd);
221
insert_defvals2([#me{entrytype = variable, assocList = Alist, aliasname = Name}
224
case snmp_misc:assq(variable_info, Alist) of
226
case VarInfo#variable_info.defval of
229
Atom = merge_atoms('default', Name),
230
io:format(Fd, "-define(~w, ~w).~n", [Atom, Val])
234
insert_defvals2(T, Fd);
235
insert_defvals2([_ | T], Fd) ->
236
insert_defvals2(T, Fd);
237
insert_defvals2([], _Fd) -> ok.
239
insert_range(Mes, Fd) ->
240
io:format(Fd, "~n%% Range values~n", []),
241
insert_range2(Mes, Fd),
242
io:format(Fd, "~n", []).
244
insert_range2([#me{imported = true} | T], Fd)->
246
insert_range2([#me{asn1_type=#asn1_type{bertype='OCTET STRING',lo=Low,hi=High},aliasname=Name}|T],Fd)->
247
case Low==undefined of
251
AtomLow = merge_atoms('low', Name),
252
AtomHigh = merge_atoms('high', Name),
253
io:format(Fd,"-define(~w, ~w).~n",[AtomLow,Low]),
254
io:format(Fd,"-define(~w, ~w).~n",[AtomHigh,High]),
257
insert_range2([#me{asn1_type=#asn1_type{bertype='Unsigned32',lo=Low,hi=High},aliasname=Name}|T],Fd)->
258
AtomLow = merge_atoms('low', Name),
259
AtomHigh = merge_atoms('high', Name),
260
io:format(Fd,"-define(~w, ~w).~n",[AtomLow,Low]),
261
io:format(Fd,"-define(~w, ~w).~n",[AtomHigh,High]),
263
insert_range2([#me{asn1_type=#asn1_type{bertype='Counter32',lo=Low,hi=High},aliasname=Name}|T],Fd)->
264
AtomLow = merge_atoms('low', Name),
265
AtomHigh = merge_atoms('high', Name),
266
io:format(Fd,"-define(~w, ~w).~n",[AtomLow,Low]),
267
io:format(Fd,"-define(~w, ~w).~n",[AtomHigh,High]),
269
insert_range2([#me{asn1_type=#asn1_type{bertype='INTEGER',lo=Low,hi=High},aliasname=Name}|T],Fd)->
270
case Low==undefined of
274
AtomLow = merge_atoms('low', Name),
275
AtomHigh = merge_atoms('high', Name),
276
io:format(Fd,"-define(~w, ~w).~n",[AtomLow,Low]),
277
io:format(Fd,"-define(~w, ~w).~n",[AtomHigh,High]),
280
insert_range2([_|T],Fd) ->
282
insert_range2([],Fd) ->
298
%%%-----------------------------------------------------------------
299
%%% Interface for erl_compile.
300
%%%-----------------------------------------------------------------
302
compile(Input, Output, Opts) ->
303
Verbose = Opts#options.verbose,
304
case convert(Input++".bin", Output++".hrl", Input, Verbose) of
308
io:format("~p", [Reason]),