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    }