/** * 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. * * @see #main(String[]) * @see daikon.Daikon.TerminationMessage */ public static void mainHelper(final String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { daikon.LogHelper.setupLogs(daikon.LogHelper.INFO); LongOpt[] longopts = new LongOpt[] { new LongOpt(Daikon.suppress_redundant_SWITCH, LongOpt.NO_ARGUMENT, null, 0), new LongOpt(Daikon.config_option_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), new LongOpt(Daikon.debugAll_SWITCH, LongOpt.NO_ARGUMENT, null, 0), new LongOpt(Daikon.debug_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), }; Getopt g = new Getopt("daikon.ExtractConsequent", args, "h", longopts); int c; while ((c = g.getopt()) != -1) { switch (c) { case 0: // got a long option String option_name = longopts[g.getLongind()].getName(); if (Daikon.help_SWITCH.equals(option_name)) { System.out.println(usage); throw new Daikon.TerminationMessage(); } else if (Daikon.suppress_redundant_SWITCH.equals(option_name)) { Daikon.suppress_redundant_invariants_with_simplify = true; } else if (Daikon.config_option_SWITCH.equals(option_name)) { String item = Daikon.getOptarg(g); daikon.config.Configuration.getInstance().apply(item); break; } else if (Daikon.debugAll_SWITCH.equals(option_name)) { Global.debugAll = true; } else if (Daikon.debug_SWITCH.equals(option_name)) { LogHelper.setLevel(Daikon.getOptarg(g), LogHelper.FINE); } else { throw new RuntimeException("Unknown long option received: " + option_name); } break; case 'h': System.out.println(usage); throw new Daikon.TerminationMessage(); case '?': break; // getopt() already printed an error default: System.out.println("getopt() returned " + c); break; } } // The index of the first non-option argument -- the name of the file int fileIndex = g.getOptind(); if (args.length - fileIndex != 1) { throw new Daikon.TerminationMessage("Wrong number of arguments." + Daikon.lineSep + usage); } String filename = args[fileIndex]; PptMap ppts = FileIO.read_serialized_pptmap( new File(filename), true // use saved config ); extract_consequent(ppts); }
private void add(PptTopLevel ppt, ValueTuple vt, int nonce) { // if this is a numbered exit, apply to the combined exit as well if (ppt.ppt_name.isNumberedExitPoint()) { // Daikon.create_combined_exits(all_ppts); PptTopLevel parent = all_ppts.get(ppt.ppt_name.makeExit()); if (parent != null) { parent.get_missingOutOfBounds(ppt, vt); add(parent, vt, nonce); } else { // make parent and apply // this is a hack. it should probably filter out orig and derived // vars instead of taking the first n. int len = ppt.num_tracevars + ppt.num_static_constant_vars; VarInfo[] exit_vars = new VarInfo[len]; for (int j = 0; j < len; j++) { exit_vars[j] = new VarInfo(ppt.var_infos[j]); exit_vars[j].varinfo_index = ppt.var_infos[j].varinfo_index; exit_vars[j].value_index = ppt.var_infos[j].value_index; exit_vars[j].equalitySet = null; } parent = new PptTopLevel(ppt.ppt_name.makeExit().getName(), exit_vars); Daikon.init_ppt(parent, all_ppts); all_ppts.add(parent); parent.get_missingOutOfBounds(ppt, vt); add(parent, vt, nonce); } } // If the point has no variables, skip it if (ppt.var_infos.length == 0) { // The sample should be skipped but Daikon does not do this so // DaikonSimple will not do this to be consistent. // The better idea is for Daikon to assert that these valuetuples are // empty and then skip the sample. assert vt.size() == 0; return; } // Instantiate slices and invariants if this is the first sample if (ppt.num_samples() == 0) { instantiate_views_and_invariants(ppt); } // manually inc the sample number because DaikonSimple does not // use any of PptTopLevel's add methods which increase the sample // number ppt.incSampleNumber(); // Loop through each slice for (Iterator<PptSlice> i = ppt.views_iterator(); i.hasNext(); ) { PptSlice slice = i.next(); Iterator<Invariant> k = slice.invs.iterator(); boolean missing = false; for (VarInfo v : slice.var_infos) { // If any var has encountered out of array bounds values, // stop all invariants in this slice. The presumption here is that // an index out of bounds implies that the derived variable (eg a[i]) // doesn't really make any sense (essentially that i is not a valid // index for a). Invariants on the derived variable are thus not // relevant. // If any variables are out of bounds, remove the invariants if (v.missingOutOfBounds()) { while (k.hasNext()) { Invariant inv = k.next(); k.remove(); } missing = true; break; } // If any variables are missing, skip this slice if (v.isMissing(vt)) { missing = true; break; } } // keep a list of the falsified invariants if (!missing) { while (k.hasNext()) { Invariant inv = k.next(); Invariant pre_inv = inv.clone(); for (VarInfo vi : inv.ppt.var_infos) { assert vt.getValue(vi) != null : vi; } if (inv.ppt instanceof PptSlice2) assert inv.ppt.var_infos.length == 2; InvariantStatus status = inv.add_sample(vt, 1); if (status == InvariantStatus.FALSIFIED) { k.remove(); } } } // update num_samples and num_values of a slice manually // because DaikonSimple does not call any of PptTopLevel's // add methods for (int j = 0; j < vt.vals.length; j++) { if (!vt.isMissing(j)) { ValueSet vs = ppt.value_sets[j]; vs.add(vt.vals[j]); } } ppt.mbtracker.add(vt, 1); } }
/** * 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); } } }