65 public class Spp { 66 public static void main(String args[]) throws Exception { 67 Map<String, String> vars = new HashMap<String, String>(); 68 Set<String> keys = new HashSet<String>(); 69 boolean be = false; 70 71 for (String arg:args) { 72 if (arg.startsWith("-D")) { 73 int i = arg.indexOf('='); 74 vars.put(arg.substring(2, i),arg.substring(i+1)); 75 } else if (arg.startsWith("-K")) { 76 keys.add(arg.substring(2)); 77 } else if ("-be".equals(arg)) { 78 be = true; 79 } else { 80 System.err.println("Usage: java build.tools.spp.Spp [-be] [-Kkey] -Dvar=value ... <in >out"); 81 System.exit(-1); 82 } 83 } 84 85 StringBuffer out = new StringBuffer(); 86 new Spp().spp(new Scanner(System.in), 87 out, "", 88 keys, vars, be, 89 false); 90 System.out.print(out.toString()); 91 } 92 93 static final String LNSEP = System.getProperty("line.separator"); 94 static final String KEY = "([a-zA-Z0-9]+)"; 95 static final String VAR = "([a-zA-Z0-9_\\-]+)"; 96 static final String TEXT = "([a-zA-Z0-9&;,.<>/#() \\$]+)"; // $ -- hack embedded $var$ 97 98 static final int GN_NOT = 1; 99 static final int GN_KEY = 2; 100 static final int GN_YES = 3; 101 static final int GN_NO = 5; 102 static final int GN_VAR = 6; 103 104 Matcher ifkey = Pattern.compile("^#if\\[(!)?" + KEY + "\\]").matcher(""); 105 Matcher elsekey = Pattern.compile("^#else\\[(!)?" + KEY + "\\]").matcher(""); 106 Matcher endkey = Pattern.compile("^#end\\[(!)?" + KEY + "\\]").matcher(""); 107 Matcher vardef = Pattern.compile("\\{#if\\[(!)?" + KEY + "\\]\\?" + TEXT + "(:"+ TEXT + ")?\\}|\\$" + VAR + "\\$").matcher(""); 108 Matcher vardef2 = Pattern.compile("\\$" + VAR + "\\$").matcher(""); 109 110 void append(StringBuffer buf, String ln, 111 Set<String> keys, Map<String, String> vars) { 112 vardef.reset(ln); 113 while (vardef.find()) { 114 String repl = ""; 115 if (vardef.group(GN_VAR) != null) 116 repl = vars.get(vardef.group(GN_VAR)); 117 else { 118 boolean test = keys.contains(vardef.group(GN_KEY)); 119 if (vardef.group(GN_NOT) != null) 120 test = !test; 121 repl = test?vardef.group(GN_YES):vardef.group(GN_NO); 122 if (repl == null) 123 repl = ""; 124 else { // embedded $var$ 125 while (vardef2.reset(repl).find()) { 126 repl = vardef2.replaceFirst(vars.get(vardef2.group(1))); 127 } 128 } 129 } 130 vardef.appendReplacement(buf, repl); 131 } 132 vardef.appendTail(buf); 133 } 134 135 // return true if #end[key], #end or EOF reached 136 boolean spp(Scanner in, StringBuffer buf, String key, 137 Set<String> keys, Map<String, String> vars, 138 boolean be, boolean skip) { 139 while (in.hasNextLine()) { 140 String ln = in.nextLine(); 141 if (be) { 142 if (ln.startsWith("#begin")) { 143 buf.setLength(0); //clean up to this line 144 continue; 145 } 146 if (ln.equals("#end")) { 147 while (in.hasNextLine()) 148 in.nextLine(); 149 return true; //discard the rest to EOF 150 } 151 } 152 if (ifkey.reset(ln).find()) { 153 String k = ifkey.group(GN_KEY); 154 boolean test = keys.contains(k); 155 if (ifkey.group(GN_NOT) != null) 156 test = !test; 157 buf.append(LNSEP); 158 if (!spp(in, buf, k, keys, vars, be, skip || !test)) { 159 spp(in, buf, k, keys, vars, be, skip || test); 160 } 161 continue; 162 } 163 if (elsekey.reset(ln).find()) { 164 if (!key.equals(elsekey.group(GN_KEY))) { 165 throw new Error("Mis-matched #if-else-end at line <" + ln + ">"); 166 } 167 buf.append(LNSEP); 168 return false; 169 } 170 if (endkey.reset(ln).find()) { 171 if (!key.equals(endkey.group(GN_KEY))) { 172 throw new Error("Mis-matched #if-else-end at line <" + ln + ">"); 173 } 174 buf.append(LNSEP); 175 return true; 176 } 177 if (ln.startsWith("#warn")) { 178 ln = "// -- This file was mechanically generated: Do not edit! -- //"; 179 } else if (ln.trim().startsWith("// ##")) { 180 ln = ""; 181 } 182 if (!skip) { 183 append(buf, ln, keys, vars); 184 } 185 buf.append(LNSEP); 186 } 187 return true; 188 } 189 } | 65 public class Spp { 66 public static void main(String args[]) throws Exception { 67 Map<String, String> vars = new HashMap<String, String>(); 68 Set<String> keys = new HashSet<String>(); 69 boolean be = false; 70 71 for (String arg:args) { 72 if (arg.startsWith("-D")) { 73 int i = arg.indexOf('='); 74 vars.put(arg.substring(2, i),arg.substring(i+1)); 75 } else if (arg.startsWith("-K")) { 76 keys.add(arg.substring(2)); 77 } else if ("-be".equals(arg)) { 78 be = true; 79 } else { 80 System.err.println("Usage: java build.tools.spp.Spp [-be] [-Kkey] -Dvar=value ... <in >out"); 81 System.exit(-1); 82 } 83 } 84 85 StringBuilder out = new StringBuilder(); 86 new Spp().spp(new Scanner(System.in), 87 out, "", 88 keys, vars, be, 89 false); 90 System.out.print(out.toString()); 91 } 92 93 static final String LNSEP = System.getProperty("line.separator"); 94 static final String TWO_LNSEPS = LNSEP + LNSEP; 95 static final String KEY = "([a-zA-Z0-9]+)"; 96 static final String VAR = "([a-zA-Z0-9_\\-]+)"; 97 static final String TEXT = "([a-zA-Z0-9&;,.<>/#() \\$]+)"; // $ -- hack embedded $var$ 98 99 static final int GN_NOT = 1; 100 static final int GN_KEY = 2; 101 static final int GN_YES = 3; 102 static final int GN_NO = 5; 103 static final int GN_VAR = 6; 104 105 Matcher ifkey = Pattern.compile("^#if\\[(!)?" + KEY + "\\]").matcher(""); 106 Matcher elsekey = Pattern.compile("^#else\\[(!)?" + KEY + "\\]").matcher(""); 107 Matcher endkey = Pattern.compile("^#end\\[(!)?" + KEY + "\\]").matcher(""); 108 Matcher vardef = Pattern.compile("\\{#if\\[(!)?" + KEY + "\\]\\?" + TEXT + "(:"+ TEXT + ")?\\}|\\$" + VAR + "\\$").matcher(""); 109 Matcher vardef2 = Pattern.compile("\\$" + VAR + "\\$").matcher(""); 110 111 void append(StringBuilder buf, String ln, 112 Set<String> keys, Map<String, String> vars) { 113 vardef.reset(ln); 114 while (vardef.find()) { 115 String repl = ""; 116 if (vardef.group(GN_VAR) != null) 117 repl = vars.get(vardef.group(GN_VAR)); 118 else { 119 boolean test = keys.contains(vardef.group(GN_KEY)); 120 if (vardef.group(GN_NOT) != null) 121 test = !test; 122 repl = test?vardef.group(GN_YES):vardef.group(GN_NO); 123 if (repl == null) 124 repl = ""; 125 else { // embedded $var$ 126 while (vardef2.reset(repl).find()) { 127 repl = vardef2.replaceFirst(vars.get(vardef2.group(1))); 128 } 129 } 130 } 131 vardef.appendReplacement(buf, repl); 132 } 133 vardef.appendTail(buf); 134 } 135 136 // return true if #end[key], #end or EOF reached 137 boolean spp(Scanner in, StringBuilder buf, String key, 138 Set<String> keys, Map<String, String> vars, 139 boolean be, boolean skip) { 140 while (in.hasNextLine()) { 141 String ln = in.nextLine(); 142 if (be) { 143 if (ln.startsWith("#begin")) { 144 buf.setLength(0); //clean up to this line 145 continue; 146 } 147 if (ln.equals("#end")) { 148 while (in.hasNextLine()) 149 in.nextLine(); 150 return true; //discard the rest to EOF 151 } 152 } 153 if (ifkey.reset(ln).find()) { 154 String k = ifkey.group(GN_KEY); 155 boolean test = keys.contains(k); 156 if (ifkey.group(GN_NOT) != null) 157 test = !test; 158 lineBreak(buf); 159 if (!spp(in, buf, k, keys, vars, be, skip || !test)) { 160 spp(in, buf, k, keys, vars, be, skip || test); 161 } 162 continue; 163 } 164 if (elsekey.reset(ln).find()) { 165 if (!key.equals(elsekey.group(GN_KEY))) { 166 throw new Error("Mis-matched #if-else-end at line <" + ln + ">"); 167 } 168 lineBreak(buf); 169 return false; 170 } 171 if (endkey.reset(ln).find()) { 172 if (!key.equals(endkey.group(GN_KEY))) { 173 throw new Error("Mis-matched #if-else-end at line <" + ln + ">"); 174 } 175 lineBreak(buf); 176 return true; 177 } 178 if (ln.startsWith("#warn")) { 179 ln = "// -- This file was mechanically generated: Do not edit! -- //"; 180 } else if (ln.trim().startsWith("// ##")) { 181 ln = ""; 182 } 183 if (!skip) { 184 append(buf, ln, keys, vars); 185 } 186 lineBreak(buf); 187 } 188 return true; 189 } 190 191 // Avoid printing more than two linebreaks in a row, to prevent generating test files 192 // with hundreds of consecutive blank lines. 193 private void lineBreak(StringBuilder buf) { 194 if (buf.length() < TWO_LNSEPS.length() 195 || !buf.substring(buf.length() - TWO_LNSEPS.length()).equals(TWO_LNSEPS)) { 196 buf.append(LNSEP); 197 } 198 } 199 } |