1 package antlr.build; 2 3 import antlr.Utils; 4 5 import java.io.*; 6 import java.lang.reflect.*; 7 8 /** An application-specific build tool for ANTLR. Old build 9 * was a shell script that of course is not portable. All it 10 * did though was to compile; this Java program is a portable 11 * compile script. :) 12 * 13 * This class knows how to portable invoke a system command with 14 * wildcard expansion. It also knows to how dynamically load a project 15 * description based upon the name. Actions are just method names 16 * within that object. The ANTLR object defines build and jar methods 17 * that use Tool to portably compile and jar--it is the replacement 18 * the script. 19 * 20 * I almost used Python for this, but I hate forcing users to download 21 * yet another tool just to compile this one. (Another reason not 22 * to use Ant). 23 * 24 * I am using a class to describe the build (e.g., ANTLR) rather than 25 * a file format at the moment since I am not sure how all this will 26 * progress. 27 * 28 * Properties antlr.build.compiler and antlr.build.root may be set 29 * according to your needs. They default to "javac" and ".". The 30 * root is the dir containing the antlr directory associated with 31 * the antlr Java package. 32 * 33 * To build this builder, run "javac *.java" in this dir. 34 * 35 * To build ANTLR, just run 36 * 37 * java antlr.build.Tool build" 38 * 39 * from the 40 * directory containing package antlr's "antlr" dir. Or, use 41 * something like: 42 * 43 * java -Dantlr.build.root=/usr/local/antlr-2.7.2 antlr.build.Tool build 44 * 45 * To make the antlr.jar file, use 46 * 47 * java antlr.build.Tool jar 48 */ 49 public class Tool { 50 public String os = null; 51 Tool()52 public Tool() { 53 os = System.getProperty("os.name"); 54 } 55 main(String[] args)56 public static void main(String[] args) { 57 if ( args.length!=1 ) { 58 System.err.println("usage: java antlr.build.Tool action"); 59 return; 60 } 61 String app = "antlr.build.ANTLR"; // hardcode to build ANTLR app 62 String action = args[0]; 63 Tool t = new Tool(); 64 t.perform(app, action); 65 } 66 67 /** Find a class named after the app and then find a method within 68 * that is named after the action. 69 */ perform(String app, String action)70 public void perform(String app, String action) { 71 if ( app==null || action==null ) { 72 error("missing app or action"); 73 return; 74 } 75 Class c = null; 76 Method m = null; 77 Object appObj = null; 78 try { 79 appObj = Utils.createInstanceOf(app); 80 } 81 catch (Exception e) { 82 // try again with antlr.build.app 83 try { 84 if ( !app.startsWith("antlr.build.") ) { 85 c = Utils.loadClass("antlr.build."+app); 86 } 87 error("no such application "+app, e); 88 } 89 catch (Exception e2) { 90 error("no such application "+app, e2); 91 } 92 } 93 if ( c==null || appObj==null ) { 94 return; 95 } 96 try { 97 m = c.getMethod(action, new Class[] {antlr.build.Tool.class}); 98 //log("begin "+action+" on "+app); 99 m.invoke(appObj, new Object[] {this}); 100 //log("end "+action+" on "+app); 101 } 102 catch (Exception e) { 103 error("no such action for application "+app, e); 104 } 105 } 106 107 /** A portable system command execution routine that logs stdout/stderr 108 * and handles cmd-line wildcards properly. 109 */ system(String cmd)110 public void system(String cmd) { 111 Runtime rt = Runtime.getRuntime(); 112 try { 113 log(cmd); 114 Process proc = null; 115 if ( !os.startsWith("Windows") ) { 116 // assume unixen if not windoze (windoze tool expands *) 117 proc = rt.exec(new String[] {"sh","-c",cmd}); 118 } 119 else { 120 proc = rt.exec(cmd); 121 } 122 StreamScarfer stderrScarfer = 123 new StreamScarfer(proc.getErrorStream(), "stderr", this); 124 StreamScarfer stdoutScarfer = 125 new StreamScarfer(proc.getInputStream(), "stdout", this); 126 stderrScarfer.start(); 127 stdoutScarfer.start(); 128 int exitVal = proc.waitFor(); 129 } 130 catch (Exception e) { 131 error("cannot exec "+cmd, e); 132 } 133 } 134 135 /** Run ANTLR on a grammar file, leaving the output in the directory of the 136 * grammar file. 137 */ antlr(String fullyQualifiedFilename)138 public void antlr(String fullyQualifiedFilename) { 139 String path = null; 140 try { 141 path = new File(fullyQualifiedFilename).getParent(); 142 if ( path!=null ) { 143 path = new File(path).getCanonicalPath(); 144 } 145 } 146 catch (IOException ioe) { 147 error("Invalid grammar file: "+fullyQualifiedFilename); 148 } 149 if ( path!=null ) { 150 log("java antlr.Tool -o "+path+" "+fullyQualifiedFilename); 151 antlr.Tool theTool = new antlr.Tool(); 152 theTool.doEverything(new String[] {"-o", path, fullyQualifiedFilename}); 153 } 154 } 155 156 /** Stdout from executing sub tools */ stdout(String s)157 public void stdout(String s) { 158 System.out.println(s); 159 } 160 161 /** Stderr from executing sub tools */ stderr(String s)162 public void stderr(String s) { 163 System.err.println(s); 164 } 165 error(String msg)166 public void error(String msg) { 167 System.err.println("antlr.build.Tool: "+msg); 168 } 169 log(String cmd)170 public void log(String cmd) { 171 System.out.println("executing: "+cmd); 172 } 173 error(String msg, Exception e)174 public void error(String msg, Exception e) { 175 System.err.println("antlr.build.Tool: "+msg); 176 e.printStackTrace(System.err); 177 } 178 } 179