/**
   * This does the work of main, but it never calls System.exit, so it is appropriate to be called
   * progrmmatically. Termination of the program with a message to the user is indicated by throwing
   * Daikon.TerminationMessage.
   *
   * <p>Difference from Daikon's mainHelper: turn off optimization flags (equality, dynamic
   * constants, NIS suppression).
   *
   * @see #main(String[])
   * @see daikon.Daikon.TerminationMessage
   * @see daikon.Daikon#mainHelper(String[])
   */
  public static void mainHelper(final String[] args) throws IOException, FileNotFoundException {

    // set up logging information
    daikon.LogHelper.setupLogs(daikon.LogHelper.INFO);

    // No optimizations used in the simple incremental algorithm so
    // optimizations are turned off.
    Daikon.use_equality_optimization = false;
    Daikon.dkconfig_use_dynamic_constant_optimization = false;
    Daikon.suppress_implied_controlled_invariants = false;
    NIS.dkconfig_enabled = false;

    // The flag tells FileIO and Daikon to use DaikonSimple
    // specific methods (e.g. FileIO.read_declaration_file).
    // When FileIO reads and processes
    // samples, it must use the SimpleProcessor rather than the
    // default Processor.
    Daikon.using_DaikonSimple = true;

    // Read command line options
    Daikon.FileOptions files = Daikon.read_options(args, usage);
    // DaikonSimple does not supply nor use the spinfo_files and map_files
    Set<File> decls_files = files.decls;
    Set<String> dtrace_files = files.dtrace;

    if ((decls_files.size() == 0) && (dtrace_files.size() == 0)) {
      throw new Daikon.TerminationMessage("No .decls or .dtrace files specified");
    }

    // Create the list of all invariant types
    Daikon.setup_proto_invs();

    // Create the program points for enter and numbered exits and
    // initializes the points (adding orig and derived variables)
    all_ppts = FileIO.read_declaration_files(decls_files);

    // Create the combined exits (and add orig and derived vars)
    // Daikon.create_combined_exits(all_ppts);

    // Read and process the data trace files
    SimpleProcessor processor = new SimpleProcessor();
    FileIO.read_data_trace_files(dtrace_files, all_ppts, processor, true);

    // System.exit(0);

    // Print out the invariants for each program point (sort first)
    for (Iterator<PptTopLevel> t = all_ppts.pptIterator(); t.hasNext(); ) {
      PptTopLevel ppt = t.next();

      // We do not need to print out program points that have not seen
      // any samples.
      if (ppt.num_samples() == 0) {
        continue;
      }
      List<Invariant> invs = PrintInvariants.sort_invariant_list(ppt.invariants_vector());
      List<Invariant> filtered_invs = Daikon.filter_invs(invs);
      // The dkconfig_quiet printing is used for creating diffs between
      // DaikonSimple
      // and Daikon's output. The second kind of printing is used for
      // debugging. Since the names of the program points are the same for both
      // Daikon and DaikonSimple, diffing the two output will result in
      // only differences in the invariants, but we can not see at which program
      // points these differing invariants appear. Using the second kind of
      // printing,
      // Daikon's output does not have the '+' in the program point name, so in
      // addition
      // to the invariants showing up in the diff, we will also see the program
      // point
      // names.

      if (Daikon.dkconfig_quiet) {
        System.out.println("====================================================");
        System.out.println(ppt.name());
      } else {
        System.out.println("===================================================+");
        System.out.println(ppt.name() + " +");
      }

      // Sometimes the program points actually differ in number of
      // samples seen due to differences in how Daikon and DaikonSimple
      // see the variable hierarchy.
      System.out.println(ppt.num_samples());

      for (Invariant inv : filtered_invs) {
        System.out.println(inv.getClass());
        System.out.println(inv);
      }
    }
  }