/** Eliminates all non-normal variables from varInfos. See isNormalVar() for details. */ private static VarInfo[] filterNonVars(VarInfo[] varInfos) { List<VarInfo> filteredList = new ArrayList<VarInfo>(); for (int i = 0; i < varInfos.length; i++) { if (isNormalVar(varInfos[i])) { filteredList.add(varInfos[i]); } else { // System.out.println("filterNonVars removed " + varInfos[i].name.name()); } } return filteredList.toArray(new VarInfo[0]); }
/** * requires: condition is a string representation of a conditional * * @return a list of all possible variable variable names in condition. arrays appear with "[]" at * the end if their elements or accessed in the condition. */ private static List<String> findPossibleClassVariables(String condition) throws ParseException { NodeToken[] tokens = TokenExtractor.extractTokens(condition); // System.out.println("TokenExtractor.extractTokens(" + condition + ") ==> " + // ArraysMDE.toString(tokens)); List<String> variables = new ArrayList<String>(); if (tokens.length >= 1) { if (tokens[0].kind == IDENTIFIER && (tokens.length <= 1 || tokens[1].kind != LPAREN)) { variables.add(tokens[0].tokenImage); } } if (tokens.length >= 2) { if (tokens[1].kind == IDENTIFIER && (tokens.length <= 2 || tokens[2].kind != LPAREN) && (!variables.contains(tokens[1].tokenImage))) { variables.add(tokens[1].tokenImage); } } for (int i = 2; i < tokens.length - 1; i++) { NodeToken token = tokens[i]; if (token.kind == IDENTIFIER && tokens[i - 1].kind != DOT && tokens[i + 1].kind != LPAREN && (!variables.contains(token.tokenImage))) { variables.add(token.tokenImage); } } if (tokens.length >= 3) { int lastIndex = tokens.length - 1; if (tokens[lastIndex].kind == IDENTIFIER && tokens[lastIndex - 1].kind != DOT && (!variables.contains(tokens[lastIndex].tokenImage))) { variables.add(tokens[lastIndex].tokenImage); } } // System.out.println("findPossibleClassVariables(" + condition + ") ==> " + // variables.toString()); return variables; }
/** * Creates a new instance of VariableManager. * * @param varInfos the varInfos for the variables to be managed. * @param condition the condition in which the variables are used. */ private static VariableManager[] makeVariableManagerArray( VarInfo[] varInfos, String condition, String className) throws ParseException { List<VariableManager> variableManagerList = new ArrayList<VariableManager>(); List<String> classVars = findPossibleClassVariables(condition); for (int i = 0; i < varInfos.length; i++) { VarInfo varInfo = varInfos[i]; try { String compilableName = compilableName(varInfo, className); // System.out.println("varInfo " + varInfo.name.name() + ", compilableName=" + // compilableName + ", isNeeded=" + isNeeded(compilableName, classVars)); if (isNeeded(compilableName, classVars)) { variableManagerList.add(new VariableManager(varInfo, condition, className)); } } catch (ParseException e) { System.out.println("ParseException: " + e.toString()); } } return variableManagerList.toArray(new VariableManager[0]); }
/** * 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, StreamCorruptedException, OptionalDataException, IOException, ClassNotFoundException { daikon.LogHelper.setupLogs(daikon.LogHelper.INFO); LongOpt[] longopts = new LongOpt[] { new LongOpt(Daikon.config_option_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), new LongOpt(output_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), new LongOpt(dir_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), new LongOpt(conf_SWITCH, LongOpt.NO_ARGUMENT, null, 0), new LongOpt(filter_SWITCH, LongOpt.NO_ARGUMENT, null, 0), new LongOpt(Daikon.debugAll_SWITCH, LongOpt.NO_ARGUMENT, null, 0), new LongOpt(Daikon.debug_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), new LongOpt(Daikon.ppt_regexp_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), new LongOpt(Daikon.track_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0), }; Getopt g = new Getopt("daikon.tools.InvariantChecker", 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 (conf_SWITCH.equals(option_name)) { doConf = true; } else if (filter_SWITCH.equals(option_name)) { doFilter = true; } else if (dir_SWITCH.equals(option_name)) { dir_file = new File(g.getOptarg()); if (!dir_file.exists() || !dir_file.isDirectory()) throw new Daikon.TerminationMessage("Error reading the directory " + dir_file); } else if (output_SWITCH.equals(option_name)) { output_file = new File(g.getOptarg()); output_stream = new PrintStream(new FileOutputStream(output_file)); } else if (Daikon.config_option_SWITCH.equals(option_name)) { String item = g.getOptarg(); 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(g.getOptarg(), LogHelper.FINE); } else if (Daikon.track_SWITCH.equals(option_name)) { LogHelper.setLevel("daikon.Debug", LogHelper.FINE); String error = Debug.add_track(g.getOptarg()); if (error != null) { throw new Daikon.TerminationMessage( "Error parsing track argument '" + g.getOptarg() + "' - " + error); } } 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; } } // Loop through each filename specified for (int i = g.getOptind(); i < args.length; i++) { // Get the file and make sure it exists File file = new File(args[i]); if (!file.exists()) { throw new Error("File " + file + " not found."); } // These aren't "endsWith()" because there might be a suffix on the end // (eg, a date). String filename = file.toString(); if (filename.indexOf(".inv") != -1) { if (inv_file != null) { throw new Daikon.TerminationMessage("multiple inv files specified", usage); } inv_file = file; } else if (filename.indexOf(".dtrace") != -1) { dtrace_files.add(filename); } else { throw new Error("Unrecognized argument: " + file); } } if (dir_file == null) { checkInvariants(); return; } // Yoav additions: File[] filesInDir = dir_file.listFiles(); if (filesInDir == null || filesInDir.length == 0) throw new Daikon.TerminationMessage("The directory " + dir_file + " is empty", usage); ArrayList<File> invariants = new ArrayList<File>(); for (File f : filesInDir) if (f.toString().indexOf(".inv") != -1) invariants.add(f); if (invariants.size() == 0) throw new Daikon.TerminationMessage( "Did not find any invariant files in the directory " + dir_file, usage); ArrayList<File> dtraces = new ArrayList<File>(); for (File f : filesInDir) if (f.toString().indexOf(".dtrace") != -1) dtraces.add(f); if (dtraces.size() == 0) throw new Daikon.TerminationMessage( "Did not find any dtrace files in the directory " + dir_file, usage); System.out.println( "Collecting data for invariants files " + invariants + " and dtrace files " + dtraces); dtrace_files.clear(); for (File dtrace : dtraces) { dtrace_files.add(dtrace.toString()); } String commaLine = ""; for (File inFile : invariants) { String name = inFile.getName().replace(".inv", "").replace(".gz", ""); commaLine += "," + name; } outputComma.add(commaLine); commaLine = ""; for (File inFile : invariants) { inv_file = inFile; failedInvariants.clear(); testedInvariants.clear(); error_cnt = 0; output_stream = new PrintStream( new FileOutputStream( inFile.toString().replace(".inv", "").replace(".gz", "") + ".false-positives.txt")); checkInvariants(); output_stream.close(); int failedCount = failedInvariants.size(); int testedCount = testedInvariants.size(); String percent = toPercentage(failedCount, testedCount); commaLine += "," + percent; } outputComma.add(commaLine); System.out.println(); for (String output : outputComma) System.out.println(output); }