let main () =
  let argv = Sys.argv in
  let argc = Array.length argv in
  if  argc = 1 then help ();

  let i = ref 1 in

  let error msg =
    prerr_string ("** ERROR:  " ^ msg);
    prerr_newline ();
    exit 1
  in

  let debug msg =
    print_string msg;
    print_newline ()
  in

  let open_out filename =
    try
      open_out filename
    with Sys_error _ ->
      error ("Could not open file " ^ filename ^ " for writing.");
      raise (Invalid_argument "no file")
  in

  let open_in filename =
    try
      open_in filename
    with Sys_error _ ->
      error ("Could not open file " ^ filename ^ " for reading.");
      raise (Invalid_argument "no file")
  in

  let next_arg arg_type =
    if !i >= argc then error ("Invalid Argument.  Expecting " ^ arg_type ^ ".");
    let arg = argv.(!i) in
    incr i;
    arg
  in

  let scope = ref None in

  let get_scope () =
    match !scope with
    | None -> error ("No netlist currently loaded.")
    | Scope scope -> scope
  in

  while !i < argc do
    match next_arg "command option" with
    | "-h" | "-help"    -> help () 
 
    | "-read_fnf"  ->
      let file = next_arg "write_fnf file" in
      let channel = open_in file in
      scope := Scope (try Parser_util.parse_channel channel file Fnf_lexer.token Fnf_parser.netlist with Parser_util.Error msg -> error msg);
      close_in channel

    | "-write_fnf" ->
      let file = next_arg "write_fnf file" in
      let channel = open_out file in
      Fnf_out.output_fnf channel (get_scope ());
      close_out channel

    | "-write_verilog" ->
      let file = next_arg "verilog file" in
      let channel = open_out file in
      Fnf_verilog.output_verilog channel (get_scope ());
      close_out channel

    | "-write_vhdl" ->
      let file = next_arg "vhdl file" in
      let channel = open_out file in
      Fnf_vhdl.output_vhdl channel (get_scope ());
      close_out channel

    | "-write_jhdl" ->
      let file = next_arg "jhdl file" in
      let channel = open_out (file ^ ".java"in
      Fnf_jhdl.output_jhdl file channel (get_scope ());
      close_out channel

    | "-write_nusmv" ->
      let file = next_arg "nusmv file" in
      let channel = open_out file in
      Fnf_nusmv.output_nusmv channel (get_scope ());
      close_out channel

    | "-write_c" ->
      let file = next_arg "nusmv file" in
      let channel_c = open_out (file ^ ".c"in
      let channel_h = open_out (file ^ ".h"in
      Fnf_c.output_c channel_c channel_h (get_scope ());
      close_out channel_c;
      close_out channel_h

    | arg -> error ("Invalid argument: " ^ arg)

  done