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