aboutsummaryrefslogblamecommitdiffstats
path: root/lib/snmp/src/compile/snmpc.src
blob: 61d7a0b04f258c3edd08e42dee78b69950bb49e7 (plain) (tree)
1
2
3
4
5
6
7
8
9



                      

                                        

               
                            




                               







                                     
                





                                                              




                             
        





                                 

       




                
             




                                                   
                           








                                       




























































                                                                       
                   
                       
                     

                                 




























                                                                                 















                                                                                  































































                                                                                        













                                                                                                

                                                                                


                                                                                                
                                                                                             




                                                                                                        
                                                                                                 
                                                                     





                                                                                                            

                                                                                         






                                                                                                   



                                                                                                    
                                                                                                        


                                                                                                      







                                                                                                          






                           
 
#!/usr/bin/env escript
%% -*- erlang -*-
%%

-include_lib("kernel/include/file.hrl").

-record(state, 
        {
	 version = "%VSN%", 
         mib_file,
         outdir = "./",
         db = volatile,
	 include_dirs = ["./"],
         include_lib_dirs = [],
	 deprecated         = false,
	 group_check        = true,
	 description        = false,
	 reference          = false,
	 imports            = false,
	 module_identity    = false,
	 module_compliance  = false, 
	 agent_capabilities = false,
	 module,
	 no_defaults        = false,
	 relaxed_row_name_assigne_check = false,
	 %% The default verbosity (silence) will be filled in 
	 %% during argument processing.
	 verbosity,                       
	 warnings = false
        }).

%% --o Dir [defaults to "./"]
%% --i Dir [defaults to "./"]
%% --il Dir
%% --sgc
%% --db DB [defaults to volatile]
%% --dep
%% --desc
%% --ref
%% --imp
%% --mi
%% --mc
%% --ac
%% --mod Mod
%% --nd
%% --rrnac
%% --version
%% --verbosity V
%% --warnings
main(Args) when is_list(Args) ->
    case (catch process_args(Args)) of
	ok ->
	    usage();
        {ok, State} when is_record(State, state) ->
	    compile(State);
        {ok, Str} when is_list(Str) ->
            io:format("~s~n~n", [Str]),
            halt(1);
        {error, ReasonStr} ->
            usage(ReasonStr)
    end;
main(_) ->
    usage().

compile(State) ->
    io:format("snmpc: ~p~n", [State]),
    File    = mk_file(State),
    Options = mk_options(State),
    case snmpc:compile(File, Options) of
	{ok, BinFileName} ->
	    io:format("BinFileName: ~p~n", [BinFileName]),
	    ok;
	{error, Reason} ->
	    io:format("Reason: ~p~n", [Reason]),
	    ok
    end.

mk_file(#state{mib_file = MIB}) ->
    MIB -- ".mib".

mk_options(#state{outdir             = OutDir, 
		  db                 = DB,
		  include_dirs       = IDs,
		  include_lib_dirs   = ILDs,
		  deprecated         = Dep,
		  group_check        = GC,
		  description        = Desc,
		  reference          = Ref,
		  imports            = Imp,
		  module_identity    = MI,
		  module_compliance  = MC, 
		  agent_capabilities = AC,
		  module             = Mod,
		  no_defaults        = ND,
		  relaxed_row_name_assigne_check = RRNAC,
		  %% The default verbosity (silence) will be filled in 
		  %% during argument processing.
		  verbosity          = V, 
		  warnings           = W}) ->
    [{outdir,                        OutDir}, 
     {db,                            DB},
     {i,                             IDs},
     {il,                            ILDs},
     {group_check,                   GC},
     {verbosity,                     V}, 
     {warnings,                      W}, 
     {deprecated,                    Dep}] ++ 
	if
	    (Mod =/= undefined) ->
		[{module, Mod}];
	    true ->
		[]
	end ++ 
	maybe_option(ND,    no_defs) ++ 
	maybe_option(RRNAC, relaxed_row_name_assign_check) ++ 
	maybe_option(Desc,  description) ++ 
	maybe_option(Ref,   reference) ++ 
	maybe_option(Imp,   imports) ++ 
	maybe_option(MI,    module_identity) ++ 
	maybe_option(MC,    module_compliance) ++ 
	maybe_option(AC,    agent_capabilities).

maybe_option(true, Opt) -> [Opt];
maybe_option(_,    _)   -> [].
    
process_args([]) ->
    e("No input file");
process_args(Args) ->
    process_args(Args, #state{}).
    
process_args([], #state{verbosity = Verbosity0, mib_file = MIB} = State) ->
    if 
	(MIB =:= undefined) ->
	    e("No input file");
	true ->
	    Verbosity = 
		case Verbosity0 of
		    undefined ->
			silence;
		    _ ->
			Verbosity0
		end,
	    IPath  = lists:reverse(State#state.include_dirs),
	    IlPath = lists:reverse(State#state.include_lib_dirs),
	    {ok, State#state{verbosity        = Verbosity,
			     include_dirs     = IPath,
			     include_lib_dirs = IlPath}}
    end;
process_args([MIB], State) ->
    case (catch file:read_file_info(MIB)) of
	{ok, #file_info{type = regular}} ->
	    {ok, State#state{mib_file = MIB}};
	{ok, #file_info{type = BadType}} ->
	    e(lists:flatten(io_lib:format("~s not a file: ~w", [MIB, BadType])));
	{error, enoent} ->
	    e(lists:flatten(io_lib:format("No such file: ~s", [MIB])));
	_ ->
	    e(lists:flatten(io_lib:format("Bad file: ~s", [MIB])))
    end; 
process_args(["--help"|_Args], _State) ->
    ok;
process_args(["--version"|_Args], State) ->
    {ok, lists:flatten(io_lib:format("snmpc ~s", [State#state.version]))};
process_args(["--verbosity", Verbosity0|Args], #state{verbosity = V} = State) 
  when (V =:= undefined) ->
    Verbosity = list_to_atom(Verbosity0),
    case lists:member(Verbosity, [trace,debug,log,info,silence]) of
	true ->
	    process_args(Args, State#state{verbosity = Verbosity});
	false ->
	    e(lists:flatten(io_lib:format("Unknown verbosity: ~s", [Verbosity0])))
    end;
process_args(["--verbosity"|_Args], #state{verbosity = V}) 
  when (V =/= undefined) ->
    e(lists:flatten(io_lib:format("Verbosity already set to ~w", [V])));
process_args(["--warnings"|Args], State) ->
    process_args(Args, State#state{warnings = true});
process_args(["--o", Dir|Args], State) ->
    case (catch file:read_file_info(Dir)) of
        {ok, #file_info{type = directory}} ->
            process_args(Args, State#state{outdir = Dir});
        {ok, #file_info{type = BadType}} ->
            e(lists:flatten(io_lib:format("Not a directory: ~p (~w)", [Dir, BadType])));
        _ ->
            e(lists:flatten(io_lib:format("Bad directory: ~p", [Dir])))
    end;
process_args(["--i", Dir|Args], State) ->
    case (catch file:read_file_info(Dir)) of
        {ok, #file_info{type = directory}} ->
	    IPath = [Dir | State#state.include_dirs], 
            process_args(Args, State#state{include_dirs = IPath});
        {ok, #file_info{type = BadType}} ->
            e(lists:flatten(io_lib:format("Not a directory: ~p (~w)", [Dir, BadType])));
        _ ->
            e(lists:flatten(io_lib:format("Bad directory: ~p", [Dir])))
    end;
process_args(["--il", Dir|Args], State) ->
    case (catch file:read_file_info(Dir)) of
        {ok, #file_info{type = directory}} ->
	    IlPath = [Dir | State#state.include_lib_dirs], 
            process_args(Args, State#state{include_lib_dirs = IlPath});
        {ok, #file_info{type = BadType}} ->
            e(lists:flatten(io_lib:format("Not a directory: ~p (~w)", [Dir, BadType])));
        _ ->
            e(lists:flatten(io_lib:format("Bad directory: ~p", [Dir])))
    end;
process_args(["--db", DB0|Args], State) ->
    DB = list_to_atom(DB0),
    case lists:member(DB, [volatile,persistent,mnesia]) of
	true ->
	    process_args(Args, State#state{db = DB});
	false ->
            e(lists:flatten(io_lib:format("Invalid db: ~s", [DB0])))
    end;
process_args(["--dep"|Args], State) ->
    process_args(Args, State#state{deprecated = true});
process_args(["--sgc"|Args], State) ->
    process_args(Args, State#state{group_check = false});
process_args(["--desc"|Args], State) ->
    process_args(Args, State#state{description = true});
process_args(["--ref"|Args], State) ->
    process_args(Args, State#state{reference = true});
process_args(["--imp"|Args], State) ->
    process_args(Args, State#state{imports = true});
process_args(["--mi"|Args], State) ->
    process_args(Args, State#state{module_identity = true});
process_args(["--mod", Module0|Args], #state{module = M} = State) 
  when (M =:= undefined) ->
    Module = list_to_atom(Module0),
    process_args(Args, State#state{module = Module});
process_args(["--mod"|_Args], #state{module = M}) 
  when (M =/= undefined) ->
    e(lists:flatten(io_lib:format("Module already set to ~w", [M])));
process_args(["--nd"|Args], State) ->
    process_args(Args, State#state{no_defaults = true});
process_args(["--rrnac"|Args], State) ->
    process_args(Args, State#state{relaxed_row_name_assigne_check = true});
process_args([Arg|Args], _State) when Args =/= [] ->
    e(lists:flatten(io_lib:format("Unknown option: ~s", [Arg]))).

usage(ReasonStr) ->
    io:format("ERROR: ~s~n", [ReasonStr]),
    usage().

usage() ->
    io:format("Usage: snmpc [options] MIB.mib"
	      "~nOptions:"
	      "~n   --help                   - Prints this info."
	      "~n   --version                - Prints compiler version."
	      "~n   --verbosity <verbosity>  - Print debug info."
	      "~n                              verbosity = trace | debug | log | info | silence"
	      "~n                              Defaults to silence."
	      "~n   --warnings               - Print warning messages."
	      "~n   --o <output dir>         - The output dir."
	      "~n                              Defaults to current working dir."
	      "~n   --i <include dir>        - Add this dir to the list of dirs that will be"
	      "~n                              searched for imported (compiled) MIB files."
	      "~n                              The current workin dir will always be included. "
	      "~n   --il <include_lib dir>   - Add this dir to the list of dirs that will be"
	      "~n                              searched for imported (compiled) MIB files."
	      "~n                              It assumes that the first element in the dir name"
	      "~n                              correspond to an OTP application. For example snmp/mibs/"
	      "~n                              The current workin dir and the <snmp-home>/priv/mibs "
	      "~n                              are always listed last the includ path. "
	      "~n   --db <DB>                - Database to used for the default instrumentation."
	      "~n                              Defaults to volatile."
	      "~n   --sgc                    - This option (skip group check), if present, disables "
	      "~n                              the \"group check\" of the mib compiler. "
	      "~n                              That is, should the OBJECT-GROUP and the NOTIFICATION-GROUP "
	      "~n                              macro(s) be checked for correctness or not. "
	      "~n                              By default the check is done. "
	      "~n   --dep                    - Keep deprecated definition(s)."
	      "~n                              If not specified the compiler will ignore"
	      "~n                              deprecated definitions."
	      "~n   --desc                   - The DESCRIPTION field will be included."
	      "~n   --ref                    - The REFERENCE field will be included."
	      "~n   --imp                    - The IMPORTS field will be included."
	      "~n   --mi                     - The MODULE-IDENTITY field will be included."
	      "~n   --mc                     - The MODULE-COMPLIANCE field will be included."
	      "~n   --ac                     - The AGENT-CAPABILITIES field will be included."
	      "~n   --mod <module>           - The module which implements all the instrumentation"
	      "~n                              functions. "
	      "~n                              The name of the of all instrumentation functions"
	      "~n                              must be the same as the corresponding managed object"
	      "~n                              it implements."
	      "~n   --nd                     - The default instrumentation functions will *not* be used"
	      "~n                              if a managed object have no instrumentation function. "
	      "~n                              Instead this will be reported as an error, and the "
	      "~n                              compilation aborts. "
	      "~n   --rrnac                  - This option, if present, specifies that the row name "
	      "~n                              assign check shall not be done strictly according to"
	      "~n                              the SMI (which allows only the value 1). "
	      "~n                              With this option, all values gŕeater than zero is allowed"
	      "~n                              (>= 1). This means that the error will be converted to "
	      "~n                              a warning. "
	      "~n                              By default it is not included, but if this option is "
	      "~n                              is present it will be. "
	      "~n   "
	      "~n", []),
    halt(1).


e(Reason) ->
    throw({error, Reason}).