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 ClassfileParser
026     * @declaredat /home/jesper/git/extendj/java4/frontend/ClassfileParser.jrag:34
027     */
028    public abstract class AbstractClassfileParser extends java.lang.Object {
029      
030    
031        public static class ClassfileFormatError extends Error {
032          public ClassfileFormatError(String message) {
033            super(message);
034          }
035        }
036    
037      
038    
039        public static final boolean VERBOSE = false;
040    
041      
042    
043        protected static final int CONSTANT_Class = 7;
044    
045      
046        protected static final int CONSTANT_FieldRef = 9;
047    
048      
049        protected static final int CONSTANT_MethodRef = 10;
050    
051      
052        protected static final int CONSTANT_InterfaceMethodRef = 11;
053    
054      
055        protected static final int CONSTANT_String = 8;
056    
057      
058        protected static final int CONSTANT_Integer = 3;
059    
060      
061        protected static final int CONSTANT_Float = 4;
062    
063      
064        protected static final int CONSTANT_Long = 5;
065    
066      
067        protected static final int CONSTANT_Double = 6;
068    
069      
070        protected static final int CONSTANT_NameAndType = 12;
071    
072      
073        protected static final int CONSTANT_Utf8 = 1;
074    
075      
076    
077        private DataInputStream is;
078    
079      
080    
081        public final String name;
082    
083      
084        public CONSTANT_Class_Info classInfo;
085    
086      
087        public CONSTANT_Info[] constantPool = null;
088    
089      
090    
091        // For Java 5 and later.
092        public boolean isInnerClass = false;
093    
094      
095    
096        public AbstractClassfileParser(InputStream in, String name) {
097          this.is = new DataInputStream(new BufferedInputStream(in));
098          this.name = name;
099        }
100    
101      
102    
103        public abstract boolean outerClassNameEquals(String name);
104    
105      
106    
107        public final int next() throws IOException {
108          return is.read();
109        }
110    
111      
112    
113        public final int u1() throws IOException {
114          return is.readUnsignedByte();
115        }
116    
117      
118    
119        public final int u2() throws IOException {
120          return is.readUnsignedShort();
121        }
122    
123      
124    
125        public final int u4() throws IOException {
126          return is.readInt();
127        }
128    
129      
130    
131        public final int readInt() throws IOException {
132          return is.readInt();
133        }
134    
135      
136    
137        public final float readFloat() throws IOException {
138          return is.readFloat();
139        }
140    
141      
142    
143        public final long readLong() throws IOException {
144          return is.readLong();
145        }
146    
147      
148    
149        public final double readDouble() throws IOException {
150          return is.readDouble();
151        }
152    
153      
154    
155        public final String readUTF() throws IOException {
156          return is.readUTF();
157        }
158    
159      
160    
161        public final void skip(int length) throws IOException {
162          while (length > 0) {
163            length -= is.skip(length);
164          }
165        }
166    
167      
168    
169        public void error(String msg) throws ClassfileFormatError {
170          throw new ClassfileFormatError(msg);
171        }
172    
173      
174    
175        public final void print(String s) {
176          //System.out.print(s);
177        }
178    
179      
180    
181        public final void println(String s) {
182          print(s + "\n");
183        }
184    
185      
186    
187        public final void println() {
188          print("\n");
189        }
190    
191      
192    
193        public final void parseMagic() throws IOException {
194          if (next() != 0xca || next() != 0xfe || next() != 0xba || next() != 0xbe) {
195            error("magic error");
196          }
197        }
198    
199      
200    
201        public final int parseMinor() throws IOException {
202          return u2();
203        }
204    
205      
206    
207        public final int parseMajor() throws IOException {
208          return u2();
209        }
210    
211      
212    
213        public final String parseThisClass() throws IOException {
214          int index = u2();
215          CONSTANT_Class_Info info = (CONSTANT_Class_Info) constantPool[index];
216          classInfo = info;
217          return info.simpleName();
218        }
219    
220      
221    
222        public final Access parseSuperClass() throws IOException {
223          int index = u2();
224          if (index == 0) {
225            return null;
226          }
227          CONSTANT_Class_Info info = (CONSTANT_Class_Info) constantPool[index];
228          return info.access();
229        }
230    
231      
232    
233        public final List parseInterfaces(List list) throws IOException {
234          int count = u2();
235          for (int i = 0; i < count; i++) {
236            CONSTANT_Class_Info info = (CONSTANT_Class_Info) constantPool[u2()];
237            list.add(info.access());
238          }
239          return list;
240        }
241    
242      
243    
244        public void parseFields(TypeDecl typeDecl) throws IOException {
245          int count = u2();
246          if (VERBOSE) {
247            println("Fields (" + count + "):");
248          }
249          for (int i = 0; i < count; i++) {
250            if (VERBOSE) {
251              print(" Field nbr " + i + " ");
252            }
253            FieldInfo fieldInfo = new FieldInfo(this);
254            if (!fieldInfo.isSynthetic()) {
255              typeDecl.addBodyDecl(fieldInfo.bodyDecl());
256            }
257          }
258        }
259    
260      
261    
262        public static Modifiers modifiers(int flags) {
263          Modifiers m = new Modifiers();
264          if ((flags & 0x0001) != 0) {
265            m.addModifier(new Modifier("public"));
266          }
267          if ((flags & 0x0002) != 0) {
268            m.addModifier(new Modifier("private"));
269          }
270          if ((flags & 0x0004) != 0) {
271            m.addModifier(new Modifier("protected"));
272          }
273          if ((flags & 0x0008) != 0) {
274            m.addModifier(new Modifier("static"));
275          }
276          if ((flags & 0x0010) != 0) {
277            m.addModifier(new Modifier("final"));
278          }
279          if ((flags & 0x0020) != 0) {
280            m.addModifier(new Modifier("synchronized"));
281          }
282          if ((flags & 0x0040) != 0) {
283            m.addModifier(new Modifier("volatile"));
284          }
285          if ((flags & 0x0080) != 0) {
286            m.addModifier(new Modifier("transient"));
287          }
288          if ((flags & 0x0100) != 0) {
289            m.addModifier(new Modifier("native"));
290          }
291          if ((flags & 0x0400) != 0) {
292            m.addModifier(new Modifier("abstract"));
293          }
294          if ((flags & 0x0800) != 0) {
295            m.addModifier(new Modifier("strictfp"));
296          }
297          return m;
298        }
299    
300      
301    
302        private void checkLengthAndNull(int index) {
303          if (index >= constantPool.length) {
304            throw new Error("Trying to access element " + index  + " in constant pool of length " + constantPool.length);
305          }
306          if (constantPool[index] == null) {
307            throw new Error("Unexpected null element in constant pool at index " + index);
308          }
309        }
310    
311      
312    
313        public boolean validConstantPoolIndex(int index) {
314          return index < constantPool.length && constantPool[index] != null;
315        }
316    
317      
318    
319        public CONSTANT_Info getCONSTANT_Info(int index) {
320          checkLengthAndNull(index);
321          return constantPool[index];
322        }
323    
324      
325    
326        public CONSTANT_Utf8_Info getCONSTANT_Utf8_Info(int index) {
327          checkLengthAndNull(index);
328          CONSTANT_Info info = constantPool[index];
329          if (!(info instanceof CONSTANT_Utf8_Info)) {
330            throw new Error("Expected CONSTANT_Utf8_info at " + index + " in constant pool but found " + info.getClass().getName());
331          }
332          return (CONSTANT_Utf8_Info) info;
333        }
334    
335      
336    
337        public CONSTANT_Class_Info getCONSTANT_Class_Info(int index) {
338          checkLengthAndNull(index);
339          CONSTANT_Info info = constantPool[index];
340          if (!(info instanceof CONSTANT_Class_Info)) {
341            throw new Error("Expected CONSTANT_Class_info at " + index + " in constant pool but found " + info.getClass().getName());
342          }
343          return (CONSTANT_Class_Info) info;
344        }
345    
346      
347    
348        public void parseConstantPool() throws IOException {
349          int count = u2();
350          if (VERBOSE) {
351            println("constant_pool_count: " + count);
352          }
353          constantPool = new CONSTANT_Info[count + 1];
354          for (int i = 1; i < count; i++) {
355            parseConstantPoolEntry(i);
356            if (constantPool[i] instanceof CONSTANT_Long_Info
357                || constantPool[i] instanceof CONSTANT_Double_Info)
358              i++;
359          }
360        }
361    
362      
363    
364        protected abstract void parseConstantPoolEntry(int i) throws IOException;
365    
366    
367    }