001 package org.extendj.ast; 002 003 import java.util.HashSet; 004 import java.io.File; 005 import java.util.Set; 006 import java.util.Collections; 007 import java.util.Collection; 008 import java.util.ArrayList; 009 import beaver.*; 010 import java.util.*; 011 import java.io.ByteArrayOutputStream; 012 import java.io.PrintStream; 013 import java.lang.reflect.InvocationTargetException; 014 import java.lang.reflect.Method; 015 import org.jastadd.util.*; 016 import java.util.zip.*; 017 import java.io.*; 018 import org.jastadd.util.PrettyPrintable; 019 import org.jastadd.util.PrettyPrinter; 020 import java.io.FileNotFoundException; 021 import java.io.BufferedInputStream; 022 import java.io.DataInputStream; 023 /** 024 * @ast class 025 * @aspect FrontendMain 026 * @declaredat /home/jesper/git/extendj/java4/frontend/FrontendMain.jrag:68 027 */ 028 abstract public class Frontend extends java.lang.Object { 029 030 protected Program program; 031 032 033 034 /** 035 * Compile success 036 */ 037 public static final int EXIT_SUCCESS = 0; 038 039 040 041 /** 042 * Lexical/semantic error. 043 */ 044 public static final int EXIT_ERROR = 1; 045 046 047 048 /** 049 * Command-line configuration error. 050 */ 051 public static final int EXIT_CONFIG_ERROR = 2; 052 053 054 055 /** 056 * The compiler terminated by system error. 057 */ 058 public static final int EXIT_SYSTEM_ERROR = 3; 059 060 061 062 /** 063 * The compiler terminated abnormally. 064 */ 065 public static final int EXIT_UNHANDLED_ERROR = 4; 066 067 068 069 private final String name; 070 071 072 private final String version; 073 074 075 076 /** 077 * Initialize the program object. 078 */ 079 protected Frontend() { 080 this("Unknown", "0"); 081 } 082 083 084 085 /** 086 * Initialize the program object and set compiler name and version. 087 * @param name compiler name 088 * @param version compiler version 089 */ 090 protected Frontend(String name, String version) { 091 this.name = name; 092 this.version = version; 093 program = new Program(); 094 program.state().reset(); 095 } 096 097 098 099 /** 100 * Process all compilation units listed in the command-line arguments, and 101 * all compilation units referenced from those. 102 * 103 * @return 0 on success, 1 on error, 2 on configuration error, 3 on system 104 * error, 4 on unhandled error 105 */ 106 public int run(String[] args, BytecodeReader reader, JavaParser parser) { 107 108 program.resetStatistics(); 109 program.initBytecodeReader(reader); 110 program.initJavaParser(parser); 111 112 initOptions(); 113 int argResult = processArgs(args); 114 if (argResult != 0) { 115 return argResult; 116 } 117 118 Collection<String> files = program.options().files(); 119 120 if (program.options().hasOption("-version")) { 121 printVersion(); 122 return EXIT_SUCCESS; 123 } 124 125 if (program.options().hasOption("-help") || files.isEmpty()) { 126 printUsage(); 127 return EXIT_SUCCESS; 128 } 129 130 Collection<CompilationUnit> work = new LinkedList<CompilationUnit>(); 131 132 try { 133 for (String file: files) { 134 program.addSourceFile(file); 135 } 136 137 int compileResult = EXIT_SUCCESS; 138 139 // process source compilation units 140 Iterator<CompilationUnit> iter = program.compilationUnitIterator(); 141 while (iter.hasNext()) { 142 CompilationUnit unit = iter.next(); 143 work.add(unit); 144 int result = processCompilationUnit(unit); 145 switch (result) { 146 case EXIT_SUCCESS: 147 break; 148 case EXIT_UNHANDLED_ERROR: 149 return result; 150 default: 151 compileResult = result; 152 } 153 } 154 155 // Process library compilation units. 156 RobustMap<String, CompilationUnit> valueMap = (RobustMap<String, CompilationUnit>) 157 program.getLibCompilationUnitValueMap(); 158 if (valueMap != null) { 159 iter = valueMap.robustValueIterator(); 160 while (iter.hasNext()) { 161 CompilationUnit unit = iter.next(); 162 work.add(unit); 163 int result = processCompilationUnit(unit); 164 switch (result) { 165 case EXIT_SUCCESS: 166 break; 167 case EXIT_UNHANDLED_ERROR: 168 return result; 169 default: 170 compileResult = result; 171 } 172 } 173 } 174 175 if (compileResult != EXIT_SUCCESS) { 176 return compileResult; 177 } 178 179 for (CompilationUnit unit: work) { 180 if (unit != null && unit.fromSource()) { 181 long start = System.nanoTime(); 182 processNoErrors(unit); 183 program.codeGenTime += System.nanoTime() - start; 184 } 185 } 186 187 } catch (AbstractClassfileParser.ClassfileFormatError e) { 188 System.err.println(e.getMessage()); 189 return EXIT_UNHANDLED_ERROR; 190 } catch (Throwable t) { 191 System.err.println("Fatal exception:"); 192 t.printStackTrace(System.err); 193 return EXIT_UNHANDLED_ERROR; 194 } finally { 195 if (program.options().hasOption("-profile")) { 196 program.printStatistics(System.out); 197 } 198 } 199 return EXIT_SUCCESS; 200 } 201 202 203 204 private Collection<Problem> EMPTY_PROBLEM_LIST = Collections.emptyList(); 205 206 207 208 /** 209 * Processes from-source compilation units by error-checking them. 210 * This method only report semantic errors and warnings. 211 * 212 * @return zero on success, non-zero on error 213 */ 214 protected int processCompilationUnit(CompilationUnit unit) throws Error { 215 if (unit != null && unit.fromSource()) { 216 try { 217 Collection<Problem> errors = unit.parseErrors(); 218 Collection<Problem> warnings = EMPTY_PROBLEM_LIST; 219 // Compute static semantic errors when there are no parse errors 220 // or the recover from parse errors option is specified. 221 if (errors.isEmpty() || program.options().hasOption("-recover")) { 222 long start = System.nanoTime(); 223 unit.collectErrors(); 224 errors = unit.errors(); 225 warnings = unit.warnings(); 226 program.errorCheckTime += System.nanoTime() - start; 227 } 228 if (!errors.isEmpty()) { 229 processErrors(errors, unit); 230 return EXIT_ERROR; 231 } else { 232 if (!warnings.isEmpty() && !program.options().hasOption("-nowarn")) { 233 processWarnings(warnings, unit); 234 } 235 } 236 } catch (Error e) { 237 System.err.println("Encountered error while processing " + unit.pathName()); 238 throw e; 239 } 240 } 241 return EXIT_SUCCESS; 242 } 243 244 245 246 /** 247 * Initialize the command-line options. 248 * Override this method to add your own command-line options. 249 */ 250 protected void initOptions() { 251 Options options = program.options(); 252 options.initOptions(); 253 options.addKeyOption("-version"); 254 options.addKeyOption("-print"); 255 options.addKeyOption("-g"); 256 options.addKeyOption("-g:none"); 257 options.addKeyOption("-g:lines,vars,source"); 258 options.addKeyOption("-nowarn"); 259 options.addKeyOption("-verbose"); 260 options.addKeyOption("-deprecation"); 261 options.addKeyValueOption("-classpath"); 262 options.addKeyValueOption("-cp"); 263 options.addKeyValueOption("-sourcepath"); 264 options.addKeyValueOption("-bootclasspath"); 265 options.addKeyValueOption("-extdirs"); 266 options.addKeyValueOption("-d"); 267 options.addKeyValueOption("-encoding"); 268 options.addKeyValueOption("-source"); 269 options.addKeyValueOption("-target"); 270 options.addKeyOption("-help"); 271 options.addKeyOption("-O"); 272 options.addKeyOption("-J-Xmx128M"); 273 options.addKeyOption("-recover"); 274 options.addKeyOption("-XprettyPrint"); 275 options.addKeyOption("-XdumpTree"); 276 277 // non-javac options 278 options.addKeyOption("-profile"); // output profiling information 279 options.addKeyOption("-debug"); // extra debug checks and information 280 } 281 282 283 284 /** 285 * Configure the compiler with command-line arguments. 286 * @return 0 if there were no configuration errors 287 */ 288 protected int processArgs(String[] args) { 289 program.options().addOptions(args); 290 boolean error = false; 291 Collection<String> files = program.options().files(); 292 for (String file: files) { 293 if (!new File(file).isFile()) { 294 System.err.println("Error: neither a valid option nor a filename: " + file); 295 error = true; 296 } 297 } 298 return error ? EXIT_CONFIG_ERROR : EXIT_SUCCESS; 299 } 300 301 302 303 /** 304 * Print errors for a compilation unit. 305 * 306 * @param errors collection of compile problems 307 * @param unit affected compilation unit 308 */ 309 protected void processErrors(Collection<Problem> errors, CompilationUnit unit) { 310 System.err.println("Errors:"); 311 for (Iterator iter2 = errors.iterator(); iter2.hasNext(); ) { 312 System.err.println(iter2.next()); 313 } 314 } 315 316 317 318 /** 319 * Print the warnings for a compilation unit. 320 * 321 * @param warnings collection of warnings 322 * @param unit affected compilation unit 323 */ 324 protected void processWarnings(Collection<Problem> warnings, CompilationUnit unit) { 325 System.err.println("Warnings:"); 326 for (Problem warning : warnings) { 327 System.err.println(warning); 328 } 329 } 330 331 332 333 /** 334 * Called for each from-source compilation unit with no errors. 335 */ 336 protected void processNoErrors(CompilationUnit unit) { 337 } 338 339 340 341 /** 342 * Echo the command-line usage help to sysout. 343 */ 344 protected void printUsage() { 345 System.out.println(name() + " " + version()); 346 System.out.println("\n" 347 + "Usage: java " + name() + " <options> <source files>\n" 348 + " -verbose Output messages about what the compiler is doing\n" 349 + " -classpath <path> Specify where to find user class files\n" 350 + " -sourcepath <path> Specify where to find input source files\n" 351 + " -bootclasspath <path> Override location of bootstrap class files\n" 352 + " -extdirs <dirs> Override location of installed extensions\n" 353 + " -d <directory> Specify where to place generated class files\n" 354 + " -nowarn Disable warning messages\n" 355 + " -help Print a synopsis of standard options\n" 356 + " -version Print version information"); 357 } 358 359 360 361 /** 362 * Echo the version to sysout. 363 */ 364 protected void printVersion() { 365 System.out.println(name() + " " + version()); 366 } 367 368 369 370 /** 371 * @return the name of the compiler 372 */ 373 protected String name() { 374 return name; 375 } 376 377 378 379 /** 380 * @return the version of the compiler 381 */ 382 protected String version() { 383 return version; 384 } 385 386 387 }