1 3 5 22 23 package edu.neu.ccs.jmk; 24 25 import java.io.File ; 26 import java.io.PrintWriter ; 27 import java.util.Vector ; 28 29 34 final class Rule 35 { 36 private boolean verbose = false; 37 38 private static boolean makeGoals(Rule[] rules, PrintWriter out) 40 throws CommandFailedException 41 { 42 boolean made = false; 43 for (int i = 0; i < rules.length; i++) { 44 Rule rule = rules[i]; 45 if (rule.isUpdating()) 46 out.println("Circular dependency " + rule + " dropped"); 47 else if (rule.make()) 48 made = true; 49 } 50 return made; 51 } 52 53 private static void resetGoals(Rule[] rules) { 55 for (int i = 0; i < rules.length; i++) 56 rules[i].reset(); 57 } 58 59 private Make make; private String target; private File file; 62 private Rule[] prerequisites = new Rule[0]; 63 private Command[] commands = new Command[0]; 64 private int lineNumber = -1; 65 private String match = null; 67 68 73 Rule(Make make, String target) { 74 this.make = make; 75 this.target = target; 76 file = new File (StringUtils.localizePaths(target)); 77 } 78 79 88 void merge(Rule[] addedPrerequisites, 89 Command[] commands, 90 int lineNumber) 91 { 92 if (prerequisites.length == 0) 93 prerequisites = addedPrerequisites; 94 else if (addedPrerequisites.length > 0) { 95 Rule[] old = prerequisites; 96 int len = old.length; 97 prerequisites = new Rule[len + addedPrerequisites.length]; 98 for (int i = 0; i < len; i++) 99 prerequisites[i] = old[i]; 100 for (int i = 0; i < addedPrerequisites.length; i++) 101 prerequisites[len + i] = addedPrerequisites[i]; 102 } 103 if (this.commands.length == 0) 104 this.commands = commands; 105 if (this.lineNumber == -1) 106 this.lineNumber = lineNumber; 107 } 108 109 112 String getTarget() { 113 return target; 114 } 115 116 120 String getLocalizedTarget() { 121 return file.getPath(); 122 } 123 124 127 private void setMatch(String match) { 128 this.match = StringUtils.localizePaths(match); 129 } 130 131 136 private void checkPatterns() { 137 if (commands.length > 0) 138 return; 139 make.tryPatterns(this); 140 } 141 142 145 boolean tryPattern(String match, String [] dependencies, 146 Command[] commands, int lineNumber) { 147 setMatch(match); 148 Rule[] addedPrerequisites = prerequisites; 150 prerequisites = new Rule[dependencies.length]; 151 for (int i = 0; i < dependencies.length; i++) prerequisites[i] = make.get(dependencies[i]); merge(addedPrerequisites, commands, lineNumber); 154 return true; 155 } 156 157 159 private boolean made = false; 160 161 private boolean isMade() { return made; 163 } 164 165 private boolean used = false; 167 private boolean updating = false; 168 169 boolean isUpdating() { return updating; 171 } 172 173 private boolean phony = false; 175 void setPhony(boolean phony) { 176 this.phony = phony; 177 } 178 179 private boolean patternsChecked = false; 181 boolean make() 182 throws CommandFailedException 183 { 184 if (made) return made; 186 if (!patternsChecked) { checkPatterns(); 188 patternsChecked = true; 189 } 190 verbose = make.isVerbose(); 191 PrintWriter out = make.getOut(); 192 if (verbose) { 193 if (prerequisites.length > 0 || commands.length > 0) 194 out.println(" Making " + getTarget()); 195 } 196 used = true; 197 try { updating = true; Rule[] remakeRules; 200 made = makeGoals(prerequisites, out); 201 boolean targetExists = exists(); 202 if (targetExists) { 203 remakeRules = checkDates(); 205 if (verbose) { 206 out.print(" Date "); 207 printRule(out, this); 208 out.println(); 209 } 210 if (remakeRules.length == 0) { 211 if (verbose) 212 out.println(" " + getTarget() + " is up to date"); 213 return made; 214 } 215 } 216 else { 217 if (verbose) { 218 out.println(" Missing " + getTarget()); 219 } 220 remakeRules = prerequisites; if (remakeRules.length == 0 && commands.length == 0) { 222 String msg = "No way to make " + getTarget(); 223 throw new CommandFailedException(msg); 224 } 225 } 226 made = runCommands(remakeRules, out) || made; 227 cachedLastModified = 0L; lastModified(); 229 if (targetExists && !made) { 230 String msg = "Make of " + getTarget() + " failed"; 232 throw new CommandFailedException(msg); 233 } 234 if (verbose) { 235 if (made) { 236 out.print(" Made "); 237 printRule(out, this); 238 out.println(" because of"); 239 for (int i = 0; i < remakeRules.length; i++) { 240 out.print(" "); 241 printRule(out, remakeRules[i]); 242 out.println(); 243 } 244 } 245 else if (prerequisites.length > 0 || commands.length > 0) 246 out.println(" Nothing to do for " + getTarget()); 247 } 248 return made; 249 } 250 finally { 251 updating = false; 252 } 253 } 254 255 private boolean exists() { 256 if (phony) return false; else 259 return file.exists(); 260 } 261 262 private long cachedLastModified = 0L; 263 264 private long lastModified() { 267 if (cachedLastModified == 0L) 268 cachedLastModified = file.lastModified(); 269 return cachedLastModified; 270 } 271 272 private Rule[] checkDates() { 275 Vector v = new Vector (); 276 cachedLastModified = 0L; 278 long whenModified = lastModified(); for (int i = 0; i < prerequisites.length; i++) { 280 long dependModified = prerequisites[i].lastModified(); 281 if (dependModified == 0L || whenModified < dependModified) 282 v.addElement(prerequisites[i]); 283 } 284 Rule[] rules = new Rule[v.size()]; 285 v.copyInto(rules); 286 return rules; 287 } 288 289 293 private boolean runCommands(Rule[] newer, PrintWriter out) 294 throws CommandFailedException 295 { 296 Rule first = null; 297 if (prerequisites.length > 0) 298 first = prerequisites[0]; 299 for (int i = 0; i < commands.length; i++) { 300 if (make.isInterruptEnabled()) throw new CommandFailedException("make interrupted"); 302 commands[i].run(this, first, newer, match, 303 make.isJustPrinting(), out); 304 } 305 return commands.length > 0; 306 } 307 308 311 private void printRule(PrintWriter out, Rule rule) { 312 out.print(rule.getTarget() + " (" + rule.lastModified() + ")"); 313 } 314 315 319 void reset() { 320 cachedLastModified = 0L; 321 if (used) { 322 used = false; 323 made = false; 324 updating = false; 325 resetGoals(prerequisites); 326 } 327 } 328 } 329 | Popular Tags |