001    /* Copyright 2000, 2001, Compaq Computer Corporation */
002    
003    package javafe.reader;
004    
005    import java.io.*;
006    
007    import javafe.ast.CompilationUnit;
008    import javafe.ast.TypeDecl;
009    import javafe.ast.TypeDeclVec;
010    import javafe.ast.TypeDeclElemVec;
011    import javafe.ast.ImportDeclVec;
012    import javafe.ast.PrettyPrint;                  // Debugging methods only
013    
014    import javafe.genericfile.*;
015    
016    /**
017     * A BinReader is a Reader that reads in CompilationUnits from binary
018     * files (.class files).
019     *
020     * <p> BinReaders do not cache the results of their reading and always
021     * return spec files.
022     *
023     * <p> TypeDecls produced by BinReaders always have specOnly set.
024     *
025     * <p> This version is not known to work on Java 1.1 class files.
026     * Later versions are planned to return CompilationUnits with stubs
027     * where inner classes should be.  It is then the caller's
028     * responsibility to call this class repeatedly to obtain all the
029     * inner classes then stitch them together in a single seamless
030     * CompilationUnit.  (Most likely, a new class will be introduced to
031     * perform this function, mapping P.N's to Compilation Units.
032     */
033    
034    public class BinReader extends Reader
035    {
036        /***************************************************
037         *                                                 *
038         * Reading:                                        *
039         *                                                 *
040         **************************************************/
041    
042        /**
043         * Attempt to read and parse a CompilationUnit from *binary*
044         * target.   Any errors encountered are reported via
045         * javafe.util.ErrorSet.  Null is returned iff an error was
046         * encountered.<p>
047         *
048         *
049         * We always return a spec file.  (avoidSpec is ignored)<p>
050         *
051         *
052         * This function is not cached.<p>
053         *
054         * Target must be non-null.<p>
055         */
056        public CompilationUnit read(/*@non_null*/GenericFile target, boolean avoidSpec) {
057            javafe.util.Info.out("[loading " + target.getHumanName() + "]");
058            try {
059                ASTClassFileParser parser = new ASTClassFileParser(target,false);
060                    // if the 2nd argument above is false, omit all bodies.
061                    // For some reason, despite the comment above, bodies are
062                    // sometimes included.
063                TypeDeclVec types =
064                    TypeDeclVec.make(new TypeDecl[] { parser.typeDecl });
065                TypeDeclElemVec emptyTypeDeclElemVec = TypeDeclElemVec.make();
066                ImportDeclVec emptyImportDeclVec = ImportDeclVec.make();
067                CompilationUnit result = 
068                    CompilationUnit.make(parser.classPackage,
069                                         null,
070                                         emptyImportDeclVec,
071                                         types,
072                                         parser.classLocation,
073                                         emptyTypeDeclElemVec); 
074                return result;
075            }
076            catch (IOException e)
077            {
078              javafe.util.ErrorSet.error("I/O error: " + e.getMessage());
079            }
080            catch (ClassFormatError e)
081            {
082              javafe.util.ErrorSet.error("Class format error: " + e.getMessage());
083            }
084    
085            return null;
086        }
087    
088        /***************************************************
089         *                                                 *
090         * Test methods:                                   *
091         *                                                 *
092         **************************************************/
093    
094        //@ requires \nonnullelements(args);
095        public static void main(String[] args) {
096            if (args.length != 1) {
097                System.err.println("BinReader: <source filename>");
098                System.exit(1);
099            }
100    
101            GenericFile target = new NormalGenericFile(args[0]);
102            BinReader reader = new BinReader();
103    
104            CompilationUnit cu = reader.read(target, false);
105            if (cu != null)
106                PrettyPrint.inst.print( System.out, cu );
107        }
108    }