From: adam Date: Fri, 3 Jun 2005 05:26:47 +0000 (+0000) Subject: ClassGen->ClassFile, ClassGen.FieldOrMethodRef->MemberRef X-Git-Url: http://git.megacz.com/?p=org.ibex.classgen.git;a=commitdiff_plain;h=6c44a3470c1ae5c0e54153871805e24e394a96bb ClassGen->ClassFile, ClassGen.FieldOrMethodRef->MemberRef darcs-hash:20050603052647-5007d-f4f1e5a2d846a0d8c81fd7ae0ecede437ee50e05.gz --- diff --git a/Makefile b/Makefile index c0b0454..4a9bb40 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ $(classes): $(sources) $(JAVAC) -d build $(sources) test: $(classes) - java -cp build org.ibex.classgen.ClassGen + java -cp build org.ibex.classgen.ClassFile clean: rm -rf build/* diff --git a/src/org/ibex/classgen/CPGen.java b/src/org/ibex/classgen/CPGen.java index 052e28c..6b59a28 100644 --- a/src/org/ibex/classgen/CPGen.java +++ b/src/org/ibex/classgen/CPGen.java @@ -25,7 +25,7 @@ class CPGen { void dump(DataOutput o) throws IOException { o.writeByte(tag); } String debugToString() { return toString(); } // so we can remove this method when not debugging - abstract Object key() throws ClassGen.ClassReadExn; // be careful using this, it drags in a bunch of code + abstract Object key() throws ClassFile.ClassReadExn; // be careful using this, it drags in a bunch of code } class IntEnt extends Ent { @@ -81,14 +81,14 @@ class CPGen { } private String fixme() { throw new Error("fixme"); } - Object key() throws ClassGen.ClassReadExn { + Object key() throws ClassFile.ClassReadExn { switch(tag) { case 7: return Type.instance(((Utf8Ent)e1).s); case 8: return (((Utf8Ent)e1).s); case 9: { NameAndTypeKey nt = (NameAndTypeKey) e2.key(); Type t = Type.instance(nt.type); - if(t == null) throw new ClassGen.ClassReadExn("invalid type descriptor"); + if(t == null) throw new ClassFile.ClassReadExn("invalid type descriptor"); return new FieldRef((Type.Class)e1.key(), nt.name, t); } case 10: case 11: { @@ -160,7 +160,7 @@ class CPGen { return ent.n; } - public final Type getType(int index) throws ClassGen.ClassReadExn { + public final Type getType(int index) throws ClassFile.ClassReadExn { Ent e = getByIndex(index); if (e instanceof Utf8Ent) return Type.instance(((Utf8Ent)e).s); else return (Type)e.key(); @@ -214,8 +214,8 @@ class CPGen { ce.e1 = addUtf8(key.name); ce.e2 = addUtf8(key.type); ent = ce; - } else if(o instanceof ClassGen.FieldOrMethodRef) { - ClassGen.FieldOrMethodRef key = (ClassGen.FieldOrMethodRef) o; + } else if(o instanceof MemberRef) { + MemberRef key = (MemberRef) o; int tag = o instanceof FieldRef ? 9 : o instanceof MethodRef ? 10 : o instanceof MethodRef.I ? 11 : 0; if(tag == 0) throw new Error("should never happen"); CPRefEnt ce = new CPRefEnt(tag); @@ -227,7 +227,7 @@ class CPGen { } int spaces = ent instanceof LongEnt ? 2 : 1; - if(usedSlots + spaces > 65536) throw new ClassGen.Exn("constant pool full"); + if(usedSlots + spaces > 65536) throw new ClassFile.Exn("constant pool full"); ent.n = state == OPEN ? 1 : usedSlots; // refcount or index @@ -309,9 +309,9 @@ class CPGen { } } - CPGen(DataInput in) throws ClassGen.ClassReadExn, IOException { + CPGen(DataInput in) throws ClassFile.ClassReadExn, IOException { usedSlots = in.readUnsignedShort(); - if(usedSlots==0) throw new ClassGen.ClassReadExn("invalid used slots"); + if(usedSlots==0) throw new ClassFile.ClassReadExn("invalid used slots"); // these are to remember the CPRefEnt e1 and e2s we have to fix up int[] e1s = new int[usedSlots]; @@ -363,7 +363,7 @@ class CPGen { break; } default: - throw new ClassGen.ClassReadExn("invalid cp ent tag"); + throw new ClassFile.ClassReadExn("invalid cp ent tag"); } entriesByIndex[index] = e; if (e instanceof LongEnt) index++; @@ -379,30 +379,30 @@ class CPGen { } if (!(e instanceof CPRefEnt)) continue; CPRefEnt ce = (CPRefEnt) e; - if(e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassGen.ClassReadExn("invalid cp index"); + if(e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index"); ce.e1 = entriesByIndex[e1s[i]]; - if(ce.e1 == null) throw new ClassGen.ClassReadExn("invalid cp index"); + if(ce.e1 == null) throw new ClassFile.ClassReadExn("invalid cp index"); if(ce.tag != 7 && ce.tag != 8) { - if(e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassGen.ClassReadExn("invalid cp index"); + if(e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index"); ce.e2 = entriesByIndex[e2s[i]]; - if(ce.e2 == null) throw new ClassGen.ClassReadExn("invalid cp index"); + if(ce.e2 == null) throw new ClassFile.ClassReadExn("invalid cp index"); } switch(ce.tag) { case 7: case 8: - if(!(ce.e1 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent"); + if(!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent"); break; case 9: case 10: case 11: if(!(ce.e1 instanceof CPRefEnt) || ((CPRefEnt)ce.e1).tag != 7) - throw new ClassGen.ClassReadExn("expected a type ent"); + throw new ClassFile.ClassReadExn("expected a type ent"); if(!(ce.e2 instanceof CPRefEnt) || ((CPRefEnt)ce.e2).tag != 12) - throw new ClassGen.ClassReadExn("expected a name and type ent"); + throw new ClassFile.ClassReadExn("expected a name and type ent"); break; case 12: - if(!(ce.e1 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent"); - if(!(ce.e2 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent"); + if(!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent"); + if(!(ce.e2 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent"); break; } } diff --git a/src/org/ibex/classgen/ClassGen.java b/src/org/ibex/classgen/ClassFile.java similarity index 86% rename from src/org/ibex/classgen/ClassGen.java rename to src/org/ibex/classgen/ClassFile.java index 39bd113..6be6bfa 100644 --- a/src/org/ibex/classgen/ClassGen.java +++ b/src/org/ibex/classgen/ClassFile.java @@ -4,7 +4,7 @@ import java.util.*; import java.io.*; /** Class generation object representing the whole classfile */ -public class ClassGen implements CGConst { +public class ClassFile implements CGConst { private final Type.Class thisType; private final Type.Class superType; private final Type.Class[] interfaces; @@ -60,22 +60,22 @@ public class ClassGen implements CGConst { sb.append("}"); } - /** @see #ClassGen(Type.Class, Type.Class, int) */ - public ClassGen(String name, String superName, int flags) { + /** @see #ClassFile(Type.Class, Type.Class, int) */ + public ClassFile(String name, String superName, int flags) { this(Type.instance(name).asClass(), Type.instance(superName).asClass(), flags); } - /** @see #ClassGen(Type.Class, Type.Class, int, Type.Class[]) */ - public ClassGen(Type.Class thisType, Type.Class superType, int flags) { + /** @see #ClassFile(Type.Class, Type.Class, int, Type.Class[]) */ + public ClassFile(Type.Class thisType, Type.Class superType, int flags) { this(thisType, superType, flags, null); } - /** Creates a new ClassGen object + /** Creates a new ClassFile object @param thisType The type of the class to generate @param superType The superclass of the generated class (commonly Type.OBJECT) @param flags The access flags for this class (ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, and ACC_ABSTRACT) */ - public ClassGen(Type.Class thisType, Type.Class superType, int flags, Type.Class[] interfaces) { + public ClassFile(Type.Class thisType, Type.Class superType, int flags, Type.Class[] interfaces) { if((flags & ~(ACC_PUBLIC|ACC_FINAL|ACC_SUPER|ACC_INTERFACE|ACC_ABSTRACT)) != 0) throw new IllegalArgumentException("invalid flags"); this.thisType = thisType; @@ -128,13 +128,13 @@ public class ClassGen implements CGConst { public void setSourceFile(String sourceFile) { this.sourceFile = sourceFile; } /** Writes the classfile data to the file specifed - @see ClassGen#dump(OutputStream) + @see ClassFile#dump(OutputStream) */ public void dump(String file) throws IOException { dump(new File(file)); } /** Writes the classfile data to the file specified If f is a directory directory components under it are created for the package the class is in (like javac's -d option) - @see ClassGen#dump(OutputStream) + @see ClassFile#dump(OutputStream) */ public void dump(File f) throws IOException { if(f.isDirectory()) { @@ -200,18 +200,18 @@ public class ClassGen implements CGConst { attributes.dump(o); // attributes } - public ClassGen read(File f) throws ClassReadExn, IOException { + public ClassFile read(File f) throws ClassReadExn, IOException { InputStream is = new FileInputStream(f); - ClassGen ret = read(is); + ClassFile ret = read(is); is.close(); return ret; } - public ClassGen read(InputStream is) throws ClassReadExn, IOException { - return new ClassGen(new DataInputStream(new BufferedInputStream(is))); + public ClassFile read(InputStream is) throws ClassReadExn, IOException { + return new ClassFile(new DataInputStream(new BufferedInputStream(is))); } - ClassGen(DataInput i) throws ClassReadExn, IOException { + ClassFile(DataInput i) throws ClassReadExn, IOException { int magic = i.readInt(); if (magic != 0xcafebabe) throw new ClassReadExn("invalid magic: " + Long.toString(0xffffffffL & magic, 16)); minor = i.readShort(); @@ -242,27 +242,6 @@ public class ClassGen implements CGConst { public ClassReadExn(String s) { super(s); } } - /** A class representing a field or method reference. This is used as an argument to the INVOKE*, GET*, and PUT* bytecodes - @see MethodRef - @see FieldRef - @see MethodRef.I - @see FieldRef - */ - public static abstract class FieldOrMethodRef { - Type.Class klass; - String name; - String descriptor; - - FieldOrMethodRef(Type.Class klass, String name, String descriptor) { this.klass = klass; this.name = name; this.descriptor = descriptor; } - FieldOrMethodRef(FieldOrMethodRef o) { this.klass = o.klass; this.name = o.name; this.descriptor = o.descriptor; } - public boolean equals(Object o_) { - if(!(o_ instanceof FieldOrMethodRef)) return false; - FieldOrMethodRef o = (FieldOrMethodRef) o_; - return o.klass.equals(klass) && o.name.equals(name) && o.descriptor.equals(descriptor); - } - public int hashCode() { return klass.hashCode() ^ name.hashCode() ^ descriptor.hashCode(); } - } - static class AttrGen { private final CPGen cp; private final Hashtable ht = new Hashtable(); @@ -327,15 +306,15 @@ public class ClassGen implements CGConst { public static void main(String[] args) throws Exception { if (args.length==1) { if (args[0].endsWith(".class")) { - System.out.println(new ClassGen(new DataInputStream(new FileInputStream(args[0])))); + System.out.println(new ClassFile(new DataInputStream(new FileInputStream(args[0])))); } else { InputStream is = Class.forName(args[0]).getClassLoader().getResourceAsStream(args[0].replace('.', '/')+".class"); - System.out.println(new ClassGen(new DataInputStream(is))); + System.out.println(new ClassFile(new DataInputStream(is))); } } else { /* Type.Class me = new Type.Class("Test"); - ClassGen cg = new ClassGen("Test", "java.lang.Object", ACC_PUBLIC|ACC_SUPER|ACC_FINAL); + ClassFile cg = new ClassFile("Test", "java.lang.Object", ACC_PUBLIC|ACC_SUPER|ACC_FINAL); FieldGen fg = cg.addField("foo", Type.INT, ACC_PUBLIC|ACC_STATIC); MethodGen mg = cg.addMethod("main", Type.VOID, new Type[]{Type.arrayType(Type.STRING)}, ACC_STATIC|ACC_PUBLIC); diff --git a/src/org/ibex/classgen/FieldGen.java b/src/org/ibex/classgen/FieldGen.java index 479a481..cf269d0 100644 --- a/src/org/ibex/classgen/FieldGen.java +++ b/src/org/ibex/classgen/FieldGen.java @@ -3,19 +3,19 @@ package org.ibex.classgen; import java.io.*; /** Class representing a field in a generated classfile - @see ClassGen#addField */ + @see ClassFile#addField */ public class FieldGen implements CGConst { private final CPGen cp; private final String name; private final Type type; private final int flags; - private final ClassGen.AttrGen attrs; + private final ClassFile.AttrGen attrs; private Object constantValue; public String toString() { StringBuffer sb = new StringBuffer(); toString(sb); return sb.toString(); } public void toString(StringBuffer sb) { - sb.append(ClassGen.flagsToString(flags)); + sb.append(ClassFile.flagsToString(flags)); sb.append(type); sb.append(" "); sb.append(name); @@ -28,17 +28,17 @@ public class FieldGen implements CGConst { flags = in.readShort(); name = cp.getUtf8ByIndex(in.readShort()); type = cp.getType(in.readShort()); - attrs = new ClassGen.AttrGen(cp, in); + attrs = new ClassFile.AttrGen(cp, in); } - FieldGen(ClassGen owner, String name, Type type, int flags) { + FieldGen(ClassFile owner, String name, Type type, int flags) { if((flags & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT|ACC_STATIC|ACC_FINAL)) != 0) throw new IllegalArgumentException("invalid flags"); this.cp = owner.cp; this.name = name; this.type = type; this.flags = flags; - this.attrs = new ClassGen.AttrGen(cp); + this.attrs = new ClassFile.AttrGen(cp); cp.addUtf8(name); cp.addUtf8(type.getDescriptor()); diff --git a/src/org/ibex/classgen/FieldRef.java b/src/org/ibex/classgen/FieldRef.java index 62460e1..331ebe4 100644 --- a/src/org/ibex/classgen/FieldRef.java +++ b/src/org/ibex/classgen/FieldRef.java @@ -7,7 +7,7 @@ GETFIELD, PUTFIELD, GETSTATIC, and PUTSTATCI bytecodes @see CGConst#GETSTATIC @see CGConst#PUTSTATIC */ -public class FieldRef extends ClassGen.FieldOrMethodRef { +public class FieldRef extends MemberRef { /** Create a reference to field name of class c with the type t */ public FieldRef(Type.Class c, String name, Type t) { super(c, name, t.getDescriptor()); } /** Equivalent to FieldRef(new Type.Class(s), ...) diff --git a/src/org/ibex/classgen/MemberRef.java b/src/org/ibex/classgen/MemberRef.java new file mode 100644 index 0000000..3c09960 --- /dev/null +++ b/src/org/ibex/classgen/MemberRef.java @@ -0,0 +1,26 @@ +package org.ibex.classgen; + +import java.util.*; +import java.io.*; + +/** A class representing a field or method reference. This is used as an argument to the INVOKE*, GET*, and PUT* bytecodes + @see MethodRef + @see FieldRef + @see MethodRef.I + @see FieldRef +*/ +public abstract class MemberRef { + Type.Class klass; + String name; + String descriptor; + + MemberRef(Type.Class klass, String name, String descriptor) { this.klass = klass; this.name = name; this.descriptor = descriptor; } + MemberRef(MemberRef o) { this.klass = o.klass; this.name = o.name; this.descriptor = o.descriptor; } + public boolean equals(Object o_) { + if(!(o_ instanceof MemberRef)) return false; + MemberRef o = (MemberRef) o_; + return o.klass.equals(klass) && o.name.equals(name) && o.descriptor.equals(descriptor); + } + public int hashCode() { return klass.hashCode() ^ name.hashCode() ^ descriptor.hashCode(); } +} + diff --git a/src/org/ibex/classgen/MethodGen.java b/src/org/ibex/classgen/MethodGen.java index 2fde5d3..e2d3b68 100644 --- a/src/org/ibex/classgen/MethodGen.java +++ b/src/org/ibex/classgen/MethodGen.java @@ -4,7 +4,7 @@ import java.io.*; import java.util.*; /** A class representing a method in a generated classfile - @see ClassGen#addMethod */ + @see ClassFile#addMethod */ public class MethodGen implements CGConst { private final static boolean EMIT_NOPS = false; @@ -16,8 +16,8 @@ public class MethodGen implements CGConst { private final Type ret; private final Type[] args; private final int flags; - private final ClassGen.AttrGen attrs; - private final ClassGen.AttrGen codeAttrs; + private final ClassFile.AttrGen attrs; + private final ClassFile.AttrGen codeAttrs; private final Hashtable exnTable = new Hashtable(); private final Hashtable thrownExceptions = new Hashtable(); @@ -31,7 +31,7 @@ public class MethodGen implements CGConst { public String toString() { StringBuffer sb = new StringBuffer(); toString(sb, ""); return sb.toString(); } public void toString(StringBuffer sb, String constructorName) { - sb.append(ClassGen.flagsToString(flags)); + sb.append(ClassFile.flagsToString(flags)); sb.append(ret); sb.append(" "); @@ -59,10 +59,10 @@ public class MethodGen implements CGConst { //String args = descriptor.substring(1, descriptor.indexOf(')')); args = new Type[0]; // FIXME codeAttrs = null; - attrs = new ClassGen.AttrGen(cp, in); + attrs = new ClassFile.AttrGen(cp, in); } - MethodGen(ClassGen owner, String name, Type ret, Type[] args, int flags) { + MethodGen(ClassFile owner, String name, Type ret, Type[] args, int flags) { if((flags & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT|ACC_STRICT)) != 0) throw new IllegalArgumentException("invalid flags"); this.cp = owner.cp; @@ -71,8 +71,8 @@ public class MethodGen implements CGConst { this.args = args; this.flags = flags; - attrs = new ClassGen.AttrGen(cp); - codeAttrs = new ClassGen.AttrGen(cp); + attrs = new ClassFile.AttrGen(cp); + codeAttrs = new ClassFile.AttrGen(cp); cp.addUtf8(name); cp.addUtf8(getDescriptor()); @@ -511,7 +511,7 @@ public class MethodGen implements CGConst { } int codeSize = p; - if(codeSize >= 65536) throw new ClassGen.Exn("method too large in size"); + if(codeSize >= 65536) throw new ClassFile.Exn("method too large in size"); o.writeShort(maxStack); o.writeShort(maxLocals); @@ -533,7 +533,7 @@ public class MethodGen implements CGConst { switch(op) { case IINC: { Pair pair = (Pair) arg; - if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassGen.Exn("overflow of iinc arg"); + if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassFile.Exn("overflow of iinc arg"); o.writeByte(pair.i1); o.writeByte(pair.i2); break; @@ -571,7 +571,7 @@ public class MethodGen implements CGConst { if((opdata & OP_BRANCH_FLAG) != 0) { int v = pc[((Integer)arg).intValue()] - pc[i]; if(argLength == 2) { - if(v < -32768 || v > 32767) throw new ClassGen.Exn("overflow of s2 offset"); + if(v < -32768 || v > 32767) throw new ClassFile.Exn("overflow of s2 offset"); o.writeShort(v); } else if(argLength == 4) { o.writeInt(v); @@ -588,10 +588,10 @@ public class MethodGen implements CGConst { } else { int iarg = ((Integer)arg).intValue(); if(argLength == 1) { - if(iarg < -128 || iarg >= 256) throw new ClassGen.Exn("overflow of s/u1 option"); + if(iarg < -128 || iarg >= 256) throw new ClassFile.Exn("overflow of s/u1 option"); o.writeByte(iarg); } else if(argLength == 2) { - if(iarg < -32768 || iarg >= 65536) throw new ClassGen.Exn("overflow of s/u2 option"); + if(iarg < -32768 || iarg >= 65536) throw new ClassFile.Exn("overflow of s/u2 option"); o.writeShort(iarg); } else { throw new Error("should never happen"); diff --git a/src/org/ibex/classgen/MethodRef.java b/src/org/ibex/classgen/MethodRef.java index 2f69e9a..4810bbb 100644 --- a/src/org/ibex/classgen/MethodRef.java +++ b/src/org/ibex/classgen/MethodRef.java @@ -7,7 +7,7 @@ package org.ibex.classgen; @see CGConst#INVOKESPECIAL @see CGConst#INVOKEINTERFACE */ -public class MethodRef extends ClassGen.FieldOrMethodRef { +public class MethodRef extends MemberRef { /** Create a reference to method name of class c with the return type ret and the arguments args */ public MethodRef(Type.Class c, String name, Type ret, Type[] args) {