12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others. 22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 3bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/** 4bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert******************************************************************************* 5bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert* Copyright (C) 2004-2012, International Business Machines Corporation and * 6bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert* others. All Rights Reserved. * 7bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert******************************************************************************* 8bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert*/ 9bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 10bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpackage com.ibm.icu.dev.tool.docs; 11bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 12bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.BufferedReader; 13bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.File; 14bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.FileInputStream; 15bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.FileOutputStream; 16bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.FilenameFilter; 17bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.IOException; 18bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.InputStream; 19bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.InputStreamReader; 20bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.PrintStream; 21bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.ArrayList; 22bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.HashMap; 23bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.Iterator; 24bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.Map; 25bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.TreeMap; 26bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 27bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 28bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/** 29bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * A simple facility for adding C-like preprocessing to .java files. 30bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * This only understands a subset of the C preprocessing syntax. 31bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Its used to manage files that with only small differences can be 32bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * compiled for different JVMs. This changes files in place, 33bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * commenting out lines based on the current flag settings. 34bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 35bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpublic class CodeMangler { 36bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private File indir; // root of input 37bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private File outdir; // root of output 38bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private String suffix; // suffix to process, default '.jpp' 39bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private boolean recurse; // true if recurse on directories 40bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private boolean force; // true if force reprocess of files 41bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private boolean clean; // true if output is to be cleaned 42bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private boolean timestamp; // true if we read/write timestamp 43bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private boolean nonames; // true if no names in header 44bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private HashMap map; // defines 45bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private ArrayList names; // files/directories to process 46bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private String header; // sorted list of defines passed in 47bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 48bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private boolean verbose; // true if we emit debug output 49bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 50bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private static final String IGNORE_PREFIX = "//##"; 51bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private static final String HEADER_PREFIX = "//##header"; 52bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 53bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public static void main(String[] args) { 54bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert new CodeMangler(args).run(); 55bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 56bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 57bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private static final String usage = "Usage:\n" + 58bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert " CodeMangler [flags] file... dir... @argfile... \n" + 59bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-in[dir] path - root directory of input files, otherwise use current directory\n" + 60bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-out[dir] path - root directory of output files, otherwise use input directory\n" + 61bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-s[uffix] string - suffix of inputfiles to process, otherwise use '.java' (directories only)\n" + 62bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-c[lean] - remove all control flags from code on output (does not proceed if overwriting)\n" + 63bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-r[ecurse] - if present, recursively process subdirectories\n" + 64bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-f[orce] - force reprocessing of files even if timestamp and headers match\n" + 65bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-t[imestamp] - expect/write timestamp in header\n" + 66bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-dNAME[=VALUE] - define NAME with optional value VALUE\n" + 67bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert " (or -d NAME[=VALUE])\n" + 68bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-n - do not put NAME/VALUE in header\n" + 69bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "-help - print this usage message and exit.\n" + 70bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "\n" + 71bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "For file arguments, output '.java' files using the same path/name under the output directory.\n" + 72bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "For directory arguments, process all files with the defined suffix in the directory.\n" + 73bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert " (if recursing, do the same for all files recursively under each directory)\n" + 74bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "For @argfile arguments, read the specified text file (strip the '@'), and process each line of that file as \n" + 75bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "an argument.\n" + 76bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "\n" + 77bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "Directives are one of the following:\n" + 78bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert " #ifdef, #ifndef, #else, #endif, #if, #elif, #define, #undef\n" + 79bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "These may optionally be preceeded by whitespace or //.\n" + 80bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "#if, #elif args are of the form 'key == value' or 'key != value'.\n" + 81bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "Only exact character match key with value is performed.\n" + 82bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "#define args are 'key [==] value', the '==' is optional.\n"; 83bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 84bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert CodeMangler(String[] args) { 85bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert map = new HashMap(); 86bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert names = new ArrayList(); 87bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert suffix = ".java"; 88bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert clean = false; 89bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert timestamp = false; 90bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 91bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String inname = null; 92bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String outname = null; 93bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean processArgs = true; 94bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String arg = null; 95bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 96bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for (int i = 0; i < args.length; ++i) { 97bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert arg = args[i]; 98bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if ("--".equals(arg)) { 99bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert processArgs = false; 100bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (processArgs && arg.charAt(0) == '-') { 101bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (arg.startsWith("-in")) { 102bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert inname = args[++i]; 103bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-out")) { 104bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outname = args[++i]; 105bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-d")) { 106bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String id = arg.substring(2); 107bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (id.length() == 0) { 108bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert id = args[++i]; 109bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 110bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String val = ""; 111bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int ix = id.indexOf('='); 112bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (ix >= 0) { 113bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert val = id.substring(ix+1); 114bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert id = id.substring(0,ix); 115bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 116bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert map.put(id, val); 117bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-s")) { 118bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert suffix = args[++i]; 119bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-r")) { 120bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert recurse = true; 121bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-f")) { 122bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert force = true; 123bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-c")) { 124bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert clean = true; 125bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-t")) { 126bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert timestamp = true; 127bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-h")) { 128bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.print(usage); 129bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break; // stop before processing arguments, so we will do nothing 130bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-v")) { 131bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert verbose = true; 132bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (arg.startsWith("-n")) { 133bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert nonames = true; 134bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 135bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("Error: unrecognized argument '" + arg + "'"); 136bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(usage); 137bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException(arg); 138bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 139bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 140bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (arg.charAt(0) == '@') { 141bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert File argfile = new File(arg.substring(1)); 142bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (argfile.exists() && !argfile.isDirectory()) { 143bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BufferedReader br = null; 144bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 145bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert br = new BufferedReader(new InputStreamReader(new FileInputStream(argfile))); 146bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ArrayList list = new ArrayList(); 147bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for (int x = 0; x < args.length; ++x) { 148bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert list.add(args[x]); 149bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 150bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String line; 151bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert while (null != (line = br.readLine())) { 152bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert line = line.trim(); 153bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (line.length() > 0 && line.charAt(0) != '#') { 154bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("adding argument: " + line); 155bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert list.add(line); 156bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 157bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 158bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert args = (String[])list.toArray(new String[list.size()]); 159bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 160bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException e) { 161bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("error reading arg file: " + e); 162bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 163bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert finally { 164bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (br != null) { 165bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 166bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert br.close(); 167bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } catch (Exception e){ 168bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // ignore 169bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 170bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 171bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 172bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 173bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 174bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert names.add(arg); 175bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 176bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 177bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 178bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } catch (IndexOutOfBoundsException e) { 179bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String msg = "Error: argument '" + arg + "' missing value"; 180bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(msg); 181bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(usage); 182bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException(msg); 183bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 184bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 185bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String username = System.getProperty("user.dir"); 186bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (inname == null) { 187bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert inname = username; 188bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (!(inname.startsWith("\\") || inname.startsWith("/"))) { 189bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert inname = username + File.separator + inname; 190bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 191bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert indir = new File(inname); 192bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 193bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert indir = indir.getCanonicalFile(); 194bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 195bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException e) { 196bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // continue, but most likely we'll fail later 197bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 198bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!indir.exists()) { 199bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException("Input directory '" + indir.getAbsolutePath() + "' does not exist."); 200bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (!indir.isDirectory()) { 201bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException("Input path '" + indir.getAbsolutePath() + "' is not a directory."); 202bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 203bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("indir: " + indir.getAbsolutePath()); 204bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 205bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (outname == null) { 206bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outname = inname; 207bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (!(outname.startsWith("\\") || outname.startsWith("/"))) { 208bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outname = username + File.separator + outname; 209bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 210bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outdir = new File(outname); 211bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 212bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outdir = outdir.getCanonicalFile(); 213bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 214bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException e) { 215bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // continue, but most likely we'll fail later 216bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 217bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!outdir.exists()) { 218bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException("Output directory '" + outdir.getAbsolutePath() + "' does not exist."); 219bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (!outdir.isDirectory()) { 220bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException("Output path '" + outdir.getAbsolutePath() + "' is not a directory."); 221bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 222bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("outdir: " + outdir.getAbsolutePath()); 223bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 224bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (clean && suffix.equals(".java")) { 225bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 226bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (outdir.getCanonicalPath().equals(indir.getCanonicalPath())) { 227bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException("Cannot use 'clean' to overwrite .java files in same directory tree"); 228bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 229bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 230bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException e) { 231bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("possible overwrite, error: " + e.getMessage()); 232bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalArgumentException("Cannot use 'clean' to overrwrite .java files"); 233bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 234bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 235bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 236bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (names.isEmpty()) { 237bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert names.add("."); 238bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 239bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 240bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert TreeMap sort = new TreeMap(String.CASE_INSENSITIVE_ORDER); 241bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert sort.putAll(map); 242bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert Iterator iter = sort.entrySet().iterator(); 243bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert StringBuffer buf = new StringBuffer(); 244bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!nonames) { 245bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert while (iter.hasNext()) { 246bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert Map.Entry e = (Map.Entry)iter.next(); 247bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (buf.length() > 0) { 248bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert buf.append(", "); 249bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 250bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert buf.append(e.getKey()); 251bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String v = (String)e.getValue(); 252bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (v != null && v.length() > 0) { 253bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert buf.append('='); 254bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert buf.append(v); 255bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 256bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 257bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 258bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert header = buf.toString(); 259bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 260bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 261bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public int run() { 262bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return process("", (String[])names.toArray(new String[names.size()])); 263bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 264bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 265bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public int process(String path, String[] filenames) { 266bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("path: '" + path + "'"); 267bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int count = 0; 268bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for (int i = 0; i < filenames.length; ++i) { 269bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("name " + i + " of " + filenames.length + ": '" + filenames[i] + "'"); 270bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String name = path + filenames[i]; 271bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert File fin = new File(indir, name); 272bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 273bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fin = fin.getCanonicalFile(); 274bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 275bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException e) { 276bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 277bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!fin.exists()) { 278bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("File " + fin.getAbsolutePath() + " does not exist."); 279bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 280bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 281bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (fin.isFile()) { 282bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("processing file: '" + fin.getAbsolutePath() + "'"); 283bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String oname; 284bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int ix = name.lastIndexOf("."); 285bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (ix != -1) { 286bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert oname = name.substring(0, ix); 287bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 288bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert oname = name; 289bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 290bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert oname += ".java"; 291bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert File fout = new File(outdir, oname); 292bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (processFile(fin, fout)) { 293bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ++count; 294bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 295bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (fin.isDirectory()) { 296bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("recursing on directory '" + fin.getAbsolutePath() + "'"); 297bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String npath = ".".equals(name) ? path : path + fin.getName() + File.separator; 298bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert count += process(npath, fin.list(filter)); // recursive call 299bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 300bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 301bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return count; 302bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 303bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 304bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 305bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private final FilenameFilter filter = new FilenameFilter() { 306bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public boolean accept(File dir, String name) { 307bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert File f = new File(dir, name); 308bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return (f.isFile() && name.endsWith(suffix)) || (f.isDirectory() && recurse); 309bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 310bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert }; 311bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 312bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public boolean processFile(File infile, File outfile) { 313bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert File backup = null; 314bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 315bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert class State { 316bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int lc; 317bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String line; 318bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean emit = true; 319bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean tripped; 320bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private State next; 321bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 322bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public String toString() { 323bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return "line " + lc 324bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + ": '" + line 325bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' (emit: " + emit 326bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + " tripped: " + tripped 327bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + ")"; 328bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 329bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 330bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert void trip(boolean trip) { 331bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!tripped & trip) { 332bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert tripped = true; 333bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert emit = next != null ? next.emit : true; 334bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 335bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert emit = false; 336bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 337bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 338bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 339bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert State push(int lc, String line, boolean trip) { 340bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert this.lc = lc; 341bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert this.line = line; 342bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert State ret = new State(); 343bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ret.next = this; 344bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ret.emit = this.emit & trip; 345bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ret.tripped = trip; 346bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return ret; 347bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 348bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 349bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert State pop() { 350bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return next; 351bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 352bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 353bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 354bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert HashMap oldMap = null; 355bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 356bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert long outModTime = 0; 357bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 358bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 359bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert PrintStream outstream = null; 360bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert InputStream instream = new FileInputStream(infile); 361bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 362bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BufferedReader reader = new BufferedReader(new InputStreamReader(instream)); 363bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int lc = 0; 364bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert State state = new State(); 365bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String line; 366bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert while ((line = reader.readLine()) != null) { 367bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (lc == 0) { // check and write header for output file if needed 368bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean hasHeader = line.startsWith(HEADER_PREFIX); 369bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (hasHeader && !force) { 370bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert long expectLastModified = ((infile.lastModified() + 999)/1000)*1000; 371bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String headerline = HEADER_PREFIX; 372bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (header.length() > 0) { 373bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += " "; 374bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += header; 375bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 376bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (timestamp) { 377bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += " "; 378bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += String.valueOf(expectLastModified); 379bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 380bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (line.equals(headerline)) { 381bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("no changes necessary to " + infile.getCanonicalPath()); 382bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert reader.close(); 383bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; // nothing to do 384bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 385bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) { 386bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println(" old header: " + line); 387bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println(" != expected: " + headerline); 388bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 389bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 390bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 391bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // create output file directory structure 392bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String outpname = outfile.getParent(); 393bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (outpname != null) { 394bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert File outp = new File(outpname); 395bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!(outp.exists() || outp.mkdirs())) { 396bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("could not create directory: '" + outpname + "'"); 397bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert reader.close(); 398bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 399bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 400bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 401bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 402bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // if we're overwriting, use a temporary file 403bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (suffix.equals(".java")) { 404bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert backup = outfile; 405bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert try { 406bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outfile = File.createTempFile(outfile.getName(), null, outfile.getParentFile()); 407bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 408bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException ex) { 409bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(ex.getMessage()); 410bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert reader.close(); 411bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 412bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 413bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 414bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 415bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outModTime = ((outfile.lastModified()+999)/1000)*1000; // round up 416bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream = new PrintStream(new FileOutputStream(outfile)); 417bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String headerline = HEADER_PREFIX; 418bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (header.length() > 0) { 419bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += " "; 420bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += header; 421bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 422bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (timestamp) { 423bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += " "; 424bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert headerline += String.valueOf(outModTime); 425bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 426bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream.println(headerline); 427bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("header: " + headerline); 428bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 429bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // discard the old header if we had one, otherwise match this line like any other 430bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (hasHeader) { 431bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ++lc; // mark as having read a line so we never reexecute this block 432bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 433bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 434bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 435bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 436bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String[] res = new String[3]; 437bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (patMatch(line, res)) { 438bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String lead = res[0]; 439bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String key = res[1]; 440bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String val = res[2]; 441bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 442bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("directive: " + line 443bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + " key: '" + key 444bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' val: '" + val 445bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' " + state); 446bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (key.equals("ifdef")) { 447bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = state.push(lc, line, map.get(val) != null); 448bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (key.equals("ifndef")) { 449bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = state.push(lc, line, map.get(val) == null); 450bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (key.equals("else")) { 451bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state.trip(true); 452bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (key.equals("endif")) { 453bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = state.pop(); 454bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (key.equals("undef")) { 455bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (state.emit) { 456bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (oldMap == null) { 457bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert oldMap = (HashMap)map.clone(); 458bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 459bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert map.remove(val); 460bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 461bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (key.equals("define")) { 462bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (pat2Match(val, res)) { 463bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String key2 = res[0]; 464bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String val2 = res[2]; 465bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 466bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println("val2: '" + val2 467bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' key2: '" + key2 468bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "'"); 469bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (state.emit) { 470bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (oldMap == null) { 471bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert oldMap = (HashMap)map.clone(); 472bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 473bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert map.put(key2, val2); 474bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 475bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 476bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { // #if, #elif 477bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // only top level OR (||) operator is supported for now 478bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int count = 1; 479bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int index = 0; 480bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert while ((index = val.indexOf("||", index)) > 0) { 481bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert count++; 482bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert index++; 483bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 484bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String[] expressions = new String[count]; 485bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (count == 1) { 486bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert expressions[0] = val; 487bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 488bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int start = 0; 489bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert index = 0; 490bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert count = 0; 491bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert while (true) { 492bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert index = val.indexOf("||", start); 493bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (index > 0) { 494bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert expressions[count++] = val.substring(start, index); 495bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert start = index + 2; 496bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 497bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert expressions[count++] = val.substring(start); 498bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break; 499bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 500bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 501bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 502bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean eval = false; 503bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for (count = 0; count < expressions.length && !eval; count++) { 504bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (pat2Match(expressions[count], res)) { 505bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String key2 = res[0]; 506bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String val2 = res[2]; 507bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 508bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (key2.equals("defined")) { 509bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // defined command 510bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println( 511bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "index: '" + count 512bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' val2: '" + val2 513bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' key2: '" + key2 514bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "'"); 515bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert eval = map.containsKey(val2); 516bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 517bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean neq = false; 518bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (res[1].equals("!=")) { 519bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert neq = true; 520bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (!res[1].equals("==")) { 521bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("Invalid expression: '" + val); 522bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 523bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (verbose) System.out.println( 524bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert "index: '" + count 525bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' val2: '" + val2 526bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' neq: '" + neq 527bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "' key2: '" + key2 528bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert + "'"); 529bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert eval = (val2.equals(map.get(key2)) != neq); 530bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 531bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 532bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 533bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (key.equals("if")) { 534bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = state.push(lc, line, eval); 535bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (key.equals("elif")) { 536bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state.trip(eval); 537bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 538bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 539bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!clean) { 540bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert lc++; 541bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!lead.equals("//")) { 542bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream.print("//"); 543bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert line = line.substring(lead.length()); 544bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 545bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream.println(line); 546bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 547bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 548bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 549bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 550bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert lc++; 551bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String found = pat3Match(line); 552bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean hasIgnore = found != null; 553bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (state.emit == hasIgnore) { 554bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (state.emit) { 555bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert line = line.substring(found.length()); 556bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 557bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert line = IGNORE_PREFIX + line; 558bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 559bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (hasIgnore && !found.equals(IGNORE_PREFIX)) { 560bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert line = IGNORE_PREFIX + line.substring(found.length()); 561bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 562bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!clean || state.emit) { 563bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream.println(line); 564bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 565bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 566bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 567bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = state.pop(); 568bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (state != null) { 569bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println("Error: unclosed directive(s):"); 570bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert do { 571bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(state); 572bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } while ((state = state.pop()) != null); 573bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(" in file: " + outfile.getCanonicalPath()); 574bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (oldMap != null) { 575bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert map = oldMap; 576bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 577bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert reader.close(); 578bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream.close(); 579bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 580bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 581bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 582bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outstream.close(); 583bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert instream.close(); 584bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 585bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (backup != null) { 586bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (backup.exists()) { 587bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert backup.delete(); 588bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 589bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outfile.renameTo(backup); 590bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 591bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 592bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (timestamp) { 593bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert outfile.setLastModified(outModTime); // synch with timestamp 594bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 595bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 596bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (oldMap != null) { 597bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert map = oldMap; 598bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 599bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 600bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert catch (IOException e) { 601bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.err.println(e); 602bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 603bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 604bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return true; 605bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 606bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 607bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 608bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /** 609bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Perform same operation as matching on pat. on exit 610bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * leadKeyValue contains the three strings lead, key, and value. 611bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 'lead' is the portion before the #ifdef directive. 'key' is 612bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * the directive. 'value' is the portion after the directive. if 613bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * there is a match, return true, else return false. 614bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 615bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert static boolean patMatch(String line, String[] leadKeyValue) { 616bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (line.length() == 0) { 617bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 618bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 619bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!line.endsWith("\n")) { 620bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert line = line + '\n'; 621bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 622bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int mark = 0; 623bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int state = 0; 624bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert loop: for (int i = 0; i < line.length(); ++i) { 625bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert char c = line.charAt(i); 626bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert switch (state) { 627bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 0: // at start of line, haven't seen anything but whitespace yet 628bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t' || c == '\r') continue; 629bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '/') { state = 1; continue; } 630bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '#') { state = 4; continue; } 631bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 632bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 1: // have seen a single slash after start of line 633bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '/') { state = 2; continue; } 634bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 635bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 2: // have seen two or more slashes 636bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '/') continue; 637bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t' || c == '\r') { state = 3; continue; } 638bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '#') { state = 4; continue; } 639bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 640bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 3: // have seen a space after two or more slashes 641bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t' || c == '\r') continue; 642bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '#') { state = 4; continue; } 643bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 644bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 4: // have seen a '#' 645bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert leadKeyValue[0] = line.substring(mark, i-1); 646bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { mark = i; state = 5; continue; } 647bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 648bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 5: // an ascii char followed the '#' 649bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) continue; 650bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t' || c == '\n') { 651bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String key = line.substring(mark, i).toLowerCase(); 652bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (key.equals("ifdef") || 653bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("ifndef") || 654bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("else") || 655bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("endif") || 656bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("undef") || 657bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("define") || 658bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("if") || 659bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert key.equals("elif")) { 660bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert leadKeyValue[1] = key; 661bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert mark = i; 662bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 6; 663bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 664bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 665bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 666bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 667bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert default: 668bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalStateException(); 669bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 670bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 671bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (state == 6) { 672bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert leadKeyValue[2] = line.substring(mark, line.length()).trim(); 673bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return true; 674bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 675bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; // never reached, does the compiler know this? 676bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 677bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 678bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /** 679bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Perform same operation as matching on pat2. on exit 680bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * keyRelValue contains the three strings key, rel, and value. 681bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 'key' is the portion before the relation (or final word). 'rel' is 682bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * the relation, if present, either == or !=. 'value' is the final 683bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * word. if there is a match, return true, else return false. 684bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 685bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert static boolean pat2Match(String line, String[] keyRelVal) { 686bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 687bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (line.length() == 0) { 688bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 689bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 690bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[0] = keyRelVal[1] = keyRelVal[2] = ""; 691bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int mark = 0; 692bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int state = 0; 693bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String command = null; 694bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert loop: for (int i = 0; i < line.length(); ++i) { 695bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert char c = line.charAt(i); 696bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert switch (state) { 697bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 0: // saw beginning or space, no rel yet 698bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t' || c == '\n') { 699bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 700bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 701bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if ((c == '!' || c == '=')) { 702bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 703bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 704bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 1; 705bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 706bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 1: // saw start of a word 707bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t') { 708bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 2; 709bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 710bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert else if (c == '(') { 711bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert command = line.substring(0, i).trim(); 712bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (!command.equals("defined")) { 713bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 714bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 715bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[0] = command; 716bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 2; 717bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 718bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert else if (c == '!' || c == '=') { 719bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 3; 720bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 721bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 722bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 2: // saw end of word, and space 723bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == ' ' || c == '\t') { 724bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 725bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 726bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert else if (command == null && c == '(') { 727bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 728bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 729bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert else if (c == '!' || c == '=') { 730bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 3; 731bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert continue; 732bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 733bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[0] = line.substring(0, i-1).trim(); 734bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert mark = i; 735bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 4; 736bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 737bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 3: // saw end of word, and '!' or '=' 738bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '=') { 739bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[0] = line.substring(0, i-1).trim(); 740bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[1] = line.substring(i-1, i+1); 741bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert mark = i+1; 742bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert state = 4; 743bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 744bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 745bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 746bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert default: 747bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break; 748bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 749bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 750bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert switch (state) { 751bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 0: 752bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; // found nothing 753bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 1: 754bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 2: 755bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[0] = line.trim(); break; // found only a word 756bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 3: 757bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; // found a word and '!' or '=" then end of line, incomplete 758bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 4: 759bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[2] = line.substring(mark).trim(); // found a word, possible rel, and who knows what 760bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (command != null) { 761bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int len = keyRelVal[2].length(); 762bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (keyRelVal[2].charAt(len - 1) != ')') { 763bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // closing parenthesis is missing 764bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return false; 765bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 766bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert keyRelVal[2] = keyRelVal[2].substring(0, len - 1).trim(); 767bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 768bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break; 769bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert default: 770bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert throw new IllegalStateException(); 771bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 772bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return true; 773bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 774bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 775bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert static String pat3Match(String line) { 776bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int state = 0; 777bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert loop: for (int i = 0; i < line.length(); ++i) { 778bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert char c = line.charAt(i); 779bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert switch(state) { 780bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 0: if (c == ' ' || c == '\t') continue; 781bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '/') { state = 1; continue; } 782bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 783bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 1: 784bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '/') { state = 2; continue; } 785bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 786bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 2: 787bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '#') { state = 3; continue; } 788bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 789bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 3: 790bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (c == '#') return line.substring(0, i+1); 791bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 792bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert default: 793bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert break loop; 794bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 795bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 796bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return null; 797bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 798bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert} 799